plan-submit.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <template>
  2. <div>
  3. <div class="my-title">处理</div>
  4. <el-form :model="dataForm" :rules="dataRule" ref="dataForm" label-width="auto">
  5. <el-row class="my-row">
  6. <el-col :span="6">
  7. <el-form-item label="项目名称:" prop="projectName">
  8. <span>{{ dataForm.projectName }}</span>
  9. </el-form-item>
  10. </el-col>
  11. <el-col :span="6">
  12. <el-form-item label="任务号:" prop="orderCode">
  13. <span>{{ dataForm.orderCode }}</span>
  14. </el-form-item>
  15. </el-col>
  16. <el-col :span="6">
  17. <el-form-item label="技术协议:" prop="attachList1">
  18. <span class="attch-file" @click="attachDetail(dataForm.attachList1)">{{ dataForm.attachList1 == null ||
  19. dataForm.attachList1.length == 0 ? '' : dataForm.attachList1[0].fileName }}</span>
  20. </el-form-item>
  21. </el-col>
  22. <el-col :span="6">
  23. <el-form-item label="资料:" prop="attachList2">
  24. <span class="attch-file" @click="attachDetail(dataForm.attachList2)">{{ dataForm.attachList2 == null ||
  25. dataForm.attachList2.length == 0 ? '' : dataForm.attachList2[0].fileName }}</span>
  26. </el-form-item>
  27. </el-col>
  28. </el-row>
  29. <el-table :data="dataForm.proProductList" border v-loading="dataListLoading" style="width: 100%;">
  30. <el-table-column label="序号" type="index" width="100" align="center">
  31. </el-table-column>
  32. <el-table-column prop="productName" header-align="center" align="center" min-width="140"
  33. :show-tooltip-when-overflow="true" label="名称">
  34. </el-table-column>
  35. <el-table-column prop="mapNumber" header-align="center" align="center" min-width="140"
  36. :show-tooltip-when-overflow="true" label="图号">
  37. </el-table-column>
  38. <el-table-column prop="versionNumber" header-align="center" align="center" min-width="140"
  39. :show-tooltip-when-overflow="true" label="版本号">
  40. </el-table-column>
  41. <el-table-column header-align="center" align="center" label="图纸">
  42. <template slot-scope="scope">
  43. <el-button :disabled="!scope.row.proDrawings || scope.row.proDrawings.length === 0" type="text" size="small"
  44. @click="drawDetails(scope.row)">查看</el-button>
  45. </template>
  46. </el-table-column>
  47. <el-table-column header-align="center" align="center" min-width="100" :show-tooltip-when-overflow="true"
  48. label="简图">
  49. <template slot-scope="scope">
  50. <el-button v-if="scope.row.attachList2 && scope.row.attachList2.length" type="text" size="small"
  51. @click="openImagePreview(scope.row.attachList2)">
  52. 查看({{ scope.row.attachList2.length }})
  53. </el-button>
  54. <el-button v-else type="text" size="small" disabled>
  55. 查看(0)
  56. </el-button>
  57. </template>
  58. </el-table-column>
  59. <el-table-column prop="materials" header-align="center" align="center" min-width="140"
  60. :show-tooltip-when-overflow="true" label="材料">
  61. </el-table-column>
  62. <el-table-column prop="unit" header-align="center" align="center" min-width="50"
  63. :show-tooltip-when-overflow="true" label="单位">
  64. </el-table-column>
  65. <el-table-column prop="cnt" header-align="center" align="center" min-width="80"
  66. :show-tooltip-when-overflow="true" label="单套数量">
  67. </el-table-column>
  68. <el-table-column prop="productSpec" header-align="center" align="center" min-width="140"
  69. :show-tooltip-when-overflow="true" label="材料规格">
  70. </el-table-column>
  71. <el-table-column prop="size" header-align="center" align="center" min-width="140"
  72. :show-tooltip-when-overflow="true" label="净尺寸">
  73. </el-table-column>
  74. <el-table-column prop="projectName" header-align="center" align="center" min-width="140"
  75. :show-tooltip-when-overflow="true" label="表处理">
  76. </el-table-column>
  77. <el-table-column prop="heatTreatment" header-align="center" align="center" min-width="140"
  78. :show-tooltip-when-overflow="true" label="热处理">
  79. </el-table-column>
  80. <el-table-column prop="projectName" header-align="center" align="center" min-width="140"
  81. :show-tooltip-when-overflow="true" label="关重性">
  82. </el-table-column>
  83. <el-table-column prop="notes" header-align="center" align="center" min-width="140"
  84. :show-tooltip-when-overflow="true" label="备注">
  85. </el-table-column>
  86. <el-table-column fixed="right" prop="cntAll" header-align="center" align="center" min-width="80"
  87. :show-tooltip-when-overflow="true" label="任务数量">
  88. </el-table-column>
  89. <el-table-column fixed="right" prop="materialCnt" header-align="center" align="center" width="70"
  90. :show-tooltip-when-overflow="true" label="库存数">
  91. </el-table-column>
  92. <el-table-column fixed="right" prop="planCnt" header-align="center" align="center" width="100"
  93. :show-tooltip-when-overflow="true" label="计划数量">
  94. <template slot-scope="scope">
  95. <el-form-item :prop="'proProductList.' + scope.$index + '.planCnt'" :rules="dataRule.planCnt"
  96. label-width="0">
  97. <el-input v-model="scope.row.planCnt" style="width:80px" :disabled="disabled"
  98. @input="scope.row.planCnt = scope.row.planCnt.replace(/[^\d]/g, '')" />
  99. </el-form-item>
  100. </template>
  101. </el-table-column>
  102. <el-table-column fixed="right" prop="disposal" header-align="center" align="center" width="90"
  103. :show-tooltip-when-overflow="true" label="处置">
  104. <template slot-scope="scope">
  105. <div class="radio-wrapper">
  106. <el-form-item :prop="'proProductList.' + scope.$index + '.disposal'" :rules="dataRule.disposal"
  107. label-width="0">
  108. <el-radio-group v-model="scope.row.disposal" class="radio-group-wrap" :disabled="disabled">
  109. <el-radio :label="2" style="margin-left:0">采购件</el-radio>
  110. <el-radio :label="3" style="margin-left:0">委外件</el-radio>
  111. <el-radio :label="1" style="margin-left:0">自制件</el-radio>
  112. </el-radio-group>
  113. </el-form-item>
  114. </div>
  115. </template>
  116. </el-table-column>
  117. <el-table-column fixed="right" prop="isTechnology" header-align="center" align="center" width="90"
  118. :show-tooltip-when-overflow="true" label="工艺">
  119. <template slot-scope="scope">
  120. <el-form-item :prop="'proProductList.' + scope.$index + '.isTechnology'" :rules="dataRule.isTechnology"
  121. label-width="0">
  122. <el-radio-group v-model="scope.row.isTechnology" class="radio-group-wrap" :disabled="disabled">
  123. <el-radio :label="1" style="margin-left:0">需要</el-radio>
  124. <el-radio :label="2" style="margin-left:0">不需要</el-radio>
  125. </el-radio-group>
  126. </el-form-item>
  127. </template>
  128. </el-table-column>
  129. </el-table>
  130. </el-form>
  131. <span slot="footer" class="dialog-footer">
  132. <el-button @click="onChose">取消</el-button>
  133. <el-button v-if="!disabled" type="primary" @click="dataFormSubmit()" v-reClick>提交</el-button>
  134. </span>
  135. <attach-detail-dialog ref="attachDetail" />
  136. <!-- 图片预览组件(使用 v-viewer 打开大图) -->
  137. <preview-component v-if="previewVisible" ref="preview" />
  138. <project-draw-preview ref="drawPreview" />
  139. <image-preview ref="imagePreview" />
  140. </div>
  141. </template>
  142. <script>
  143. import AttachDetailDialog from '../common/attach-detail-dialog'
  144. import PreviewComponent from '../common/preview-component'
  145. import ProjectDrawPreview from '../tech/product-draw-detail-dialog.vue'
  146. import { downloadUrl } from '@/api/file'
  147. import ImagePreview from '@/views/modules/common/image-preview.vue'
  148. import ImageViewerMixin from '@/views/modules/common/mixins/image-viewer-mixin'
  149. export default {
  150. name: 'plan-submit',
  151. mixins: [ImageViewerMixin],
  152. components: { AttachDetailDialog, PreviewComponent, ProjectDrawPreview, ImagePreview },
  153. computed: {},
  154. data() {
  155. return {
  156. disabled: false,
  157. id: 0,
  158. dataForm: {
  159. proProductList: []
  160. },
  161. dataRule: {
  162. planCnt: [{ required: true, message: '请输入', trigger: 'blur' }],
  163. disposal: [{ required: true, message: '请选择', trigger: 'change' }],
  164. isTechnology: [{ required: true, message: '请选择', trigger: 'change' }]
  165. },
  166. dataList: [],
  167. dataListLoading: false,
  168. expandedRowKeys: [],
  169. treeMap: new Map(),
  170. previewVisible: false,
  171. downloadUrl: downloadUrl
  172. }
  173. },
  174. created() { },
  175. beforeDestroy() { },
  176. methods: {
  177. onChose() {
  178. this.$emit('onChose')
  179. },
  180. async init(item, readonly) {
  181. let id = item.productionManagementId
  182. if (readonly) {
  183. this.disabled = true
  184. }
  185. this.$http({
  186. url: this.$http.adornUrl(`/biz-service/projProduction/info/${id}`),
  187. method: 'get'
  188. }).then(({ data }) => {
  189. if (data && data.code === '200') {
  190. this.dataForm = data.data
  191. data.data.proProductList.map(item => {
  192. if (item.proProductList != null && item.proProductList.length > 0) {
  193. item.proProductList.map(item2 => {
  194. this.dataForm.proProductList.push(item2)
  195. })
  196. }
  197. })
  198. // console.log(this.dataForm)
  199. } else {
  200. this.$message.error(data.msg)
  201. }
  202. })
  203. },
  204. validateField(type) {
  205. this.$refs.dataForm.validateField(type)
  206. },
  207. attachDetail(attachList) {
  208. this.$nextTick(() => {
  209. this.$refs.attachDetail.init(attachList)
  210. })
  211. },
  212. drawDetails(row) {
  213. this.$refs.drawPreview && this.$refs.drawPreview.init(row.proDrawings || [])
  214. },
  215. // 过滤图片附件
  216. getImageList(attachList) {
  217. if (!attachList || !Array.isArray(attachList)) return []
  218. return attachList.filter(item => this.isImage(item && item.fileName))
  219. },
  220. isImage(fileName) {
  221. if (!fileName || typeof fileName !== 'string') return false
  222. const ext = fileName.split('.').pop().toLowerCase()
  223. return ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(ext)
  224. },
  225. // 预览大图(或其他文件走新窗口)
  226. previewFile(fileName, url) {
  227. this.previewVisible = true
  228. this.$nextTick(() => {
  229. this.$refs.preview && this.$refs.preview.init(fileName, url)
  230. })
  231. },
  232. // 表单提交
  233. dataFormSubmit() {
  234. this.$refs['dataForm'].validate((valid) => {
  235. if (valid) {
  236. let data = {
  237. orderCode: this.dataForm.orderCode,
  238. proProductList: this.dataForm.proProductList
  239. }
  240. let index = this.dataForm.proProductList.findIndex(item => item.isTechnology == null)
  241. if (index > -1) {
  242. this.$message.error("请勾选 工艺")
  243. return
  244. }
  245. // console.log('data', data)
  246. this.$http({
  247. url: this.$http.adornUrl(`/biz-service/projProduction/submitPlan`),
  248. method: 'post',
  249. data: this.$http.adornData(data)
  250. }).then(({ data }) => {
  251. if (data && data.code === '200') {
  252. this.$message({
  253. message: '操作成功',
  254. type: 'success',
  255. duration: 1500,
  256. onClose: () => {
  257. this.onChose()
  258. this.$emit('refreshDataList')
  259. }
  260. })
  261. } else {
  262. this.$message.error(data.msg)
  263. }
  264. })
  265. }
  266. })
  267. },
  268. handleExpandChange(row, expanded) {
  269. // console.log(row, expanded)
  270. if (expanded) {
  271. this.expandedRowKeys.push(row.productId)
  272. } else {
  273. const index = this.expandedRowKeys.indexOf(row.productId)
  274. if (index !== -1) {
  275. this.expandedRowKeys.splice(index, 1)
  276. }
  277. }
  278. },
  279. loadingData(row, treeNode, resolve) {
  280. // console.log('loadingData')
  281. if (!this.treeMap.has(row.productId)) {
  282. this.treeMap.set(row.productId, { row, treeNode, resolve })
  283. }
  284. row.children = row.proProductList
  285. resolve(row.proProductList)
  286. },
  287. }
  288. }
  289. </script>
  290. <style>
  291. .my-row {
  292. margin-bottom: 20px;
  293. }
  294. .radio-group-wrap {
  295. display: flex;
  296. align-items: flex-start;
  297. flex-direction: column;
  298. gap: 10px 0px;
  299. /* 行列间距控制 */
  300. }
  301. .attch-file {
  302. cursor: pointer;
  303. color: #3e8ef7;
  304. }
  305. /* 缩略图样式 */
  306. .thumb-list {
  307. display: flex;
  308. flex-wrap: wrap;
  309. gap: 6px;
  310. justify-content: center;
  311. }
  312. .thumb {
  313. width: 48px;
  314. height: 48px;
  315. object-fit: cover;
  316. border: 1px solid #ebeef5;
  317. border-radius: 4px;
  318. cursor: pointer;
  319. }
  320. </style>