You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

504 lines
14 KiB

3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
2 months ago
3 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
2 months ago
3 months ago
1 month ago
3 months ago
1 month ago
3 months ago
2 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
1 month ago
3 months ago
3 months ago
2 months ago
3 months ago
1 month ago
3 months ago
3 months ago
3 months ago
3 months ago
1 month ago
3 months ago
3 months ago
3 months ago
3 months ago
  1. <template>
  2. <div class="exp-apply-form">
  3. <el-form
  4. :model="saveHeaderData"
  5. :rules="formRules"
  6. ref="applyForm"
  7. label-position="top"
  8. style="margin-left: 5px; margin-top: -5px;">
  9. <el-row :gutter="20">
  10. <el-col :span="12">
  11. <el-form-item label="事业部" prop="buNo">
  12. <el-select
  13. v-model="saveHeaderData.buNo"
  14. :disabled="readonly || isEdit"
  15. placeholder="请选择事业部"
  16. style="width: 100%">
  17. <el-option
  18. v-for="i in buList"
  19. :key="i.buNo"
  20. :label="i.buDesc"
  21. :value="i.buNo">
  22. </el-option>
  23. </el-select>
  24. </el-form-item>
  25. </el-col>
  26. <el-col :span="12">
  27. <el-form-item label="试验类型" prop="experimentType">
  28. <el-select
  29. v-model="saveHeaderData.experimentType"
  30. :disabled="readonly"
  31. placeholder="请选择试验类型"
  32. style="width: 100%">
  33. <el-option label="High Risk" value="High Risk"></el-option>
  34. <el-option label="Low Risk" value="Low Risk"></el-option>
  35. </el-select>
  36. </el-form-item>
  37. </el-col>
  38. <el-col :span="12">
  39. <el-form-item label="试验单号" prop="applyNo">
  40. <el-input
  41. v-model="saveHeaderData.applyNo"
  42. :readonly="readonly || (isEdit && saveHeaderData.status !== '草稿' && saveHeaderData.status !== '已驳回')"
  43. placeholder="请输入试验单号">
  44. </el-input>
  45. </el-form-item>
  46. </el-col>
  47. <el-col :span="12">
  48. <el-form-item label="项目编号" prop="projectNo">
  49. <el-input
  50. v-model="saveHeaderData.projectNo"
  51. :readonly="readonly"
  52. placeholder="请输入项目编号">
  53. </el-input>
  54. </el-form-item>
  55. </el-col>
  56. <el-col :span="12">
  57. <el-form-item label="期望完成日期" prop="expectedFinishDate">
  58. <el-date-picker
  59. v-model="saveHeaderData.expectedFinishDate"
  60. :disabled="readonly"
  61. type="date"
  62. format="yyyy-MM-dd"
  63. value-format="yyyy-MM-dd"
  64. placeholder="选择日期"
  65. style="width: 100%">
  66. </el-date-picker>
  67. </el-form-item>
  68. </el-col>
  69. <el-col :span="12">
  70. <el-form-item label="试验名称" prop="title">
  71. <el-input
  72. v-model="saveHeaderData.title"
  73. :readonly="readonly"
  74. placeholder="请输入试验名称">
  75. </el-input>
  76. </el-form-item>
  77. </el-col>
  78. <el-col :span="12">
  79. <el-form-item label="试验负责人">
  80. <span v-if="!readonly" style="cursor: pointer" slot="label" @click="getBaseList(103)"><a href="#">试验负责人</a></span>
  81. <el-input v-model="saveHeaderData.projectLeader" disabled></el-input>
  82. </el-form-item>
  83. </el-col>
  84. <el-col :span="12">
  85. <el-form-item label="PJM负责人">
  86. <el-select
  87. v-model="saveHeaderData.pjmLeaderUserId"
  88. :disabled="readonly"
  89. clearable
  90. filterable
  91. placeholder="请选择PJM负责人(非必填)"
  92. style="width: 100%"
  93. @change="handlePjmLeaderChange">
  94. <el-option
  95. v-for="item in pjmLeaderList"
  96. :key="item.userId"
  97. :label="item.userDisplay || item.username"
  98. :value="item.userId">
  99. </el-option>
  100. </el-select>
  101. </el-form-item>
  102. </el-col>
  103. <el-col :span="24">
  104. <el-form-item label="试验目的" prop="purpose">
  105. <el-input
  106. v-model="saveHeaderData.purpose"
  107. :readonly="readonly"
  108. placeholder="请输入试验目的">
  109. </el-input>
  110. </el-form-item>
  111. </el-col>
  112. </el-row>
  113. <el-row :gutter="20">
  114. <!-- <el-col :span="24">
  115. <el-form-item label="验证方法及判断标准" prop="justification">
  116. <el-input
  117. v-model="saveHeaderData.justification"
  118. :readonly="readonly"
  119. placeholder="请输入验证方法及判断标准">
  120. </el-input>
  121. </el-form-item>
  122. </el-col>
  123. </el-row>
  124. <el-row :gutter="20">
  125. <el-col :span="12">
  126. <el-form-item label="试验产品型号">
  127. <el-input
  128. v-model="saveHeaderData.productType"
  129. :readonly="readonly"
  130. placeholder="请输入产品型号">
  131. </el-input>
  132. </el-form-item>
  133. </el-col>-->
  134. <el-col :span="24">
  135. <el-form-item label="申请数量">
  136. <el-input
  137. v-model="saveHeaderData.quantityReq"
  138. :readonly="readonly"
  139. :rows="3" type="textarea"
  140. placeholder="请输入申请数量描述">
  141. </el-input>
  142. </el-form-item>
  143. </el-col>
  144. </el-row>
  145. <el-row :gutter="20" style="margin-top: 45px">
  146. <el-col :span="24">
  147. <el-form-item label="工序">
  148. <el-input
  149. v-model="saveHeaderData.processRequirement"
  150. :readonly="readonly"
  151. type="textarea"
  152. :rows="3"
  153. placeholder="工序">
  154. </el-input>
  155. </el-form-item>
  156. </el-col>
  157. </el-row>
  158. <!-- <el-row :gutter="20">
  159. &lt;!&ndash; <el-col :span="12">
  160. <el-form-item label="联系方式">
  161. <el-input
  162. v-model="saveHeaderData.contactMethod"
  163. :readonly="readonly"
  164. placeholder="请输入联系方式">
  165. </el-input>
  166. </el-form-item>
  167. </el-col>&ndash;&gt;
  168. </el-row>-->
  169. <!-- <el-row :gutter="20">
  170. <el-col :span="24">
  171. <el-form-item label="工艺、取样、测试要求">
  172. <el-input
  173. v-model="saveHeaderData.processRequirement"
  174. :readonly="readonly"
  175. type="textarea"
  176. :rows="3"
  177. placeholder="请输入工艺、取样、测试要求">
  178. </el-input>
  179. </el-form-item>
  180. </el-col>
  181. </el-row>-->
  182. <!-- 只读模式下显示的附加信息 -->
  183. <template v-if="readonly && saveHeaderData.applyNo">
  184. <el-divider content-position="left">试验单信息</el-divider>
  185. <el-row :gutter="20">
  186. <el-col :span="8">
  187. <el-form-item label="试验单号">
  188. <span>{{ saveHeaderData.applyNo }}</span>
  189. </el-form-item>
  190. </el-col>
  191. <el-col :span="8">
  192. <el-form-item label="状态">
  193. <el-tag :type="getStatusType(saveHeaderData.status)">
  194. {{ getStatusText(saveHeaderData.status) }}
  195. </el-tag>
  196. </el-form-item>
  197. </el-col>
  198. <el-col :span="8">
  199. <el-form-item label="申请人">
  200. <span>{{ saveHeaderData.creatorName }}</span>
  201. </el-form-item>
  202. </el-col>
  203. </el-row>
  204. <el-row :gutter="20">
  205. <el-col :span="12">
  206. <el-form-item label="创建时间">
  207. <span>{{ saveHeaderData.createTime }}</span>
  208. </el-form-item>
  209. </el-col>
  210. <el-col :span="12">
  211. <el-form-item label="更新时间">
  212. <span>{{ saveHeaderData.updateTime }}</span>
  213. </el-form-item>
  214. </el-col>
  215. </el-row>
  216. </template>
  217. </el-form>
  218. <!-- 用户选择弹窗 -->
  219. <Chooselist ref="baseList" @getBaseData="getBaseData"></Chooselist>
  220. </div>
  221. </template>
  222. <script>
  223. import { saveExpApply, getPjmLeaderList } from '@/api/erf/erf'
  224. import { getBuList } from '@/api/factory/site'
  225. import Chooselist from '@/views/modules/common/Chooselist'
  226. export default {
  227. name: 'ExpApplyForm',
  228. components: { Chooselist },
  229. props: {
  230. applyData: {
  231. type: Object,
  232. default: () => ({})
  233. },
  234. readonly: {
  235. type: Boolean,
  236. default: false
  237. }
  238. },
  239. data() {
  240. return {
  241. buList: [],
  242. pjmLeaderList: [],
  243. saveHeaderData: {
  244. applyNo: '',
  245. originalApplyNo: '',
  246. buNo: '',
  247. experimentType: '',
  248. projectNo: '',
  249. title: '',
  250. purpose: '',
  251. justification: '',
  252. productType: '',
  253. quantityReq: '',
  254. expectedFinishDate: '',
  255. projectLeaderName: this.$store.state.user.name,
  256. projectLeader: this.$store.state.user.userDisplay,
  257. pjmLeaderUserId: null,
  258. pjmLeaderName: '',
  259. contactMethod: '',
  260. processRequirement: '',
  261. creatorUserId: this.$store.state.user.id,
  262. creatorName: this.$store.state.user.userDisplay
  263. },
  264. formRules: {
  265. applyNo: [
  266. { required: true, message: '请输入试验单号', trigger: 'blur' }
  267. ],
  268. buNo: [
  269. { required: true, message: '请选择事业部', trigger: 'change' }
  270. ],
  271. experimentType: [
  272. { required: true, message: '请选择试验类型', trigger: 'change' }
  273. ],
  274. title: [
  275. { required: true, message: '请输入试验名称', trigger: 'blur' }
  276. ],
  277. projectNo: [
  278. { required: true, message: '请输入项目编号', trigger: 'blur' }
  279. ],
  280. expectedFinishDate: [
  281. { required: true, message: '请选择期望完成日期', trigger: 'change' }
  282. ]
  283. },
  284. isEdit: false,
  285. tagNo: 0
  286. }
  287. },
  288. watch: {
  289. 'saveHeaderData.buNo'(newVal, oldVal) {
  290. if (!newVal) {
  291. this.saveHeaderData.pjmLeaderUserId = null
  292. this.saveHeaderData.pjmLeaderName = ''
  293. // BU为空时回退查询全部PJM负责人
  294. this.loadPjmLeaderList('')
  295. return
  296. }
  297. if (newVal !== oldVal) {
  298. if (oldVal !== undefined && oldVal !== null && oldVal !== '') {
  299. this.saveHeaderData.pjmLeaderUserId = null
  300. this.saveHeaderData.pjmLeaderName = ''
  301. }
  302. this.loadPjmLeaderList(newVal)
  303. }
  304. }
  305. },
  306. mounted() {
  307. this.loadBuList()
  308. if (this.applyData && this.applyData.applyNo) {
  309. this.saveHeaderData = {
  310. ...this.applyData,
  311. originalApplyNo: this.applyData.applyNo
  312. }
  313. this.isEdit = true
  314. }
  315. // 首次打开弹窗时也查询一次PJM负责人(BU为空时查询全量)
  316. this.loadPjmLeaderList(this.saveHeaderData.buNo || '')
  317. },
  318. methods: {
  319. /**
  320. * 加载事业部列表
  321. */
  322. loadBuList() {
  323. const tempData = { site: this.$store.state.user.site }
  324. getBuList(tempData).then(({data}) => {
  325. if (data.code === 0) {
  326. this.buList = data.row1
  327. if (data.row1.length === 1) {
  328. this.saveHeaderData.buNo = data.row1[0].buNo
  329. }
  330. }
  331. })
  332. },
  333. /**
  334. * 加载PJM负责人列表产品文档收美-PM角色
  335. */
  336. loadPjmLeaderList(buNo) {
  337. getPjmLeaderList({ buNo: buNo || '' }).then(({data}) => {
  338. if (data && data.code === 0) {
  339. this.pjmLeaderList = data.list || []
  340. this.ensurePjmLeaderOption()
  341. if (this.saveHeaderData.pjmLeaderUserId && !this.saveHeaderData.pjmLeaderName) {
  342. this.handlePjmLeaderChange(this.saveHeaderData.pjmLeaderUserId)
  343. }
  344. } else {
  345. this.pjmLeaderList = []
  346. this.$message.error(data.msg || '加载PJM负责人失败')
  347. }
  348. }).catch(() => {
  349. this.pjmLeaderList = []
  350. this.$message.error('加载PJM负责人异常')
  351. })
  352. },
  353. /**
  354. * 处理PJM负责人变更
  355. */
  356. handlePjmLeaderChange(userId) {
  357. if (!userId) {
  358. this.saveHeaderData.pjmLeaderName = ''
  359. return
  360. }
  361. const selected = this.pjmLeaderList.find(item => item.userId === userId)
  362. this.saveHeaderData.pjmLeaderName = selected
  363. ? (selected.userDisplay || selected.username || '')
  364. : (this.saveHeaderData.pjmLeaderName || '')
  365. },
  366. /**
  367. * 编辑场景兜底已选PJM负责人不在当前下拉项时补充显示
  368. */
  369. ensurePjmLeaderOption() {
  370. if (!this.saveHeaderData.pjmLeaderUserId) {
  371. return
  372. }
  373. const exist = this.pjmLeaderList.some(item => item.userId === this.saveHeaderData.pjmLeaderUserId)
  374. if (!exist && this.saveHeaderData.pjmLeaderName) {
  375. this.pjmLeaderList.push({
  376. userId: this.saveHeaderData.pjmLeaderUserId,
  377. username: this.saveHeaderData.pjmLeaderName,
  378. userDisplay: this.saveHeaderData.pjmLeaderName
  379. })
  380. }
  381. },
  382. /**
  383. * 获取表单数据用于验证
  384. */
  385. getFormData() {
  386. let valid = false
  387. this.$refs.applyForm.validate(v => {
  388. valid = v
  389. })
  390. return valid ? this.saveHeaderData : null
  391. },
  392. /**
  393. * 保存表单
  394. */
  395. save() {
  396. return new Promise((resolve, reject) => {
  397. this.$refs.applyForm.validate(valid => {
  398. if (!valid) {
  399. reject('表单验证失败')
  400. return
  401. }
  402. saveExpApply(this.saveHeaderData).then(({data}) => {
  403. if (data && data.code === 0) {
  404. resolve(data)
  405. } else {
  406. this.$message.error(data.msg || '保存失败')
  407. reject(data.msg)
  408. }
  409. }).catch(error => {
  410. reject(error)
  411. })
  412. })
  413. })
  414. },
  415. /**
  416. * 打开用户选择弹窗
  417. * @param val tagNo标识
  418. */
  419. getBaseList(val) {
  420. this.tagNo = val
  421. this.$nextTick(() => {
  422. let strVal = ''
  423. this.$refs.baseList.init(val, strVal, '')
  424. })
  425. },
  426. /**
  427. * 用户选择弹窗回调
  428. * @param val 选中的用户数据
  429. */
  430. getBaseData(val) {
  431. if (this.tagNo === 103) {
  432. this.saveHeaderData.projectLeaderName = val.username
  433. this.saveHeaderData.projectLeader = val.user_display
  434. }
  435. },
  436. /**
  437. * 获取状态类型
  438. */
  439. getStatusType(status) {
  440. const types = {
  441. '草稿': 'info',
  442. '已提交': 'warning',
  443. '已批准': 'success',
  444. '生产中': '',
  445. '已完成': 'success',
  446. '已取消': 'danger',
  447. '已驳回': 'danger'
  448. }
  449. return types[status] || 'info'
  450. },
  451. /**
  452. * 获取状态文本直接返回中文状态
  453. */
  454. getStatusText(status) {
  455. return status || ''
  456. }
  457. }
  458. }
  459. </script>
  460. <style scoped>
  461. .exp-apply-form {
  462. padding: 10px;
  463. }
  464. </style>