project-form.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. <template>
  2. <div>
  3. <!-- <el-descriptions :column="4" size="medium" border>-->
  4. <!-- <el-descriptions-item label="项目名称" span="2">{{ form.name }}</el-descriptions-item>-->
  5. <!-- <el-descriptions-item label="项目类型">{{ form.type }}</el-descriptions-item>-->
  6. <!-- <el-descriptions-item label="项目编码">{{ form.code }}</el-descriptions-item>-->
  7. <!-- <el-descriptions-item label="从属项目">{{ form.parentId }}</el-descriptions-item>-->
  8. <!-- <el-descriptions-item label="负责部门">{{ form.responsibleDeptName }}</el-descriptions-item>-->
  9. <!-- <el-descriptions-item label="项目经理">{{ form.responsibleUserName }}</el-descriptions-item>-->
  10. <!-- <el-descriptions-item label="项目团队">{{ form.teamName }}</el-descriptions-item>-->
  11. <!-- <el-descriptions-item label="项目预算">{{ form.number }}</el-descriptions-item>-->
  12. <!-- <el-descriptions-item label="项目周期">{{ form.cycle }}</el-descriptions-item>-->
  13. <!-- <el-descriptions-item label="计划开始日期">{{ form.cycle }}</el-descriptions-item>-->
  14. <!-- <el-descriptions-item label="计划完成日期">{{ form.planEndDate }}</el-descriptions-item>-->
  15. <!-- <el-descriptions-item label="关联合同">{{ form.contractName }}</el-descriptions-item>-->
  16. <!-- <el-descriptions-item label="客户名称">{{ form.contactName }}</el-descriptions-item>-->
  17. <!-- <el-descriptions-item label="客户联系电话">{{ form.contactRelationPhone }}</el-descriptions-item>-->
  18. <!-- <el-descriptions-item label="项目简介" :span="3">{{ form.content }}</el-descriptions-item>-->
  19. <!-- <el-descriptions-item label="附件">-->
  20. <!-- <el-link-->
  21. <!-- v-for="item in form.files"-->
  22. <!-- type="primary"-->
  23. <!-- :underline="false"-->
  24. <!-- @click="downloadFile(item)">-->
  25. <!-- {{ item.name }}-->
  26. <!-- </el-link>-->
  27. <!-- </el-descriptions-item>-->
  28. <!-- </el-descriptions>-->
  29. <el-form
  30. ref="form"
  31. :model="form"
  32. :rules="rules"
  33. class="el-form-box"
  34. label-width="120px"
  35. >
  36. <el-row>
  37. <el-col :span="8">
  38. <el-form-item prop="type" label="项目类型">
  39. <!-- <dict-selection dict-name="项目类型" v-model="form.type" :disabled="dialogType=='view'"-->
  40. <!-- @change="changeType"></dict-selection>-->
  41. <ele-tree-select
  42. filterable
  43. :disabled="dialogType == 'view'"
  44. clearable
  45. :data="typeTreeList"
  46. v-model="form.type"
  47. valueKey="id"
  48. labelKey="name"
  49. placeholder="请选择"
  50. @change="changeType"
  51. default-expand-all
  52. />
  53. </el-form-item>
  54. </el-col>
  55. <el-col :span="8">
  56. <el-form-item prop="code" label="项目编码">
  57. <el-input
  58. :disabled="dialogType == 'view'"
  59. v-model="form.code"
  60. ></el-input>
  61. </el-form-item>
  62. </el-col>
  63. <el-col :span="8">
  64. <el-form-item prop="name" label="项目名称">
  65. <el-input
  66. v-model="form.name"
  67. :disabled="dialogType == 'view'"
  68. ></el-input>
  69. </el-form-item>
  70. </el-col>
  71. </el-row>
  72. <el-row>
  73. <el-col :span="8">
  74. <el-form-item label="从属项目">
  75. <ele-tree-select
  76. :disabled="dialogType == 'view'"
  77. clearable
  78. filterable
  79. :data="projectList"
  80. v-model="form.parentId"
  81. childrenKey="projectList"
  82. valueKey="id"
  83. labelKey="name"
  84. placeholder="请选择"
  85. default-expand-all
  86. />
  87. </el-form-item>
  88. </el-col>
  89. <el-col :span="8">
  90. <el-form-item label="负责部门" prop="responsibleDeptId">
  91. <ele-tree-select
  92. filterable
  93. :disabled="dialogType == 'view'"
  94. clearable
  95. :data="deptTreeList"
  96. v-model="form.responsibleDeptId"
  97. valueKey="id"
  98. labelKey="name"
  99. placeholder="请选择"
  100. @change="changeDeptInfo"
  101. default-expand-all
  102. />
  103. </el-form-item>
  104. </el-col>
  105. <el-col :span="8">
  106. <el-form-item prop="responsibleUserId" label="项目经理">
  107. <personSelect
  108. :disabled="dialogType == 'view'"
  109. ref="directorRef"
  110. :init="false"
  111. v-model="form.responsibleUserId"
  112. @selfChange="personChange"
  113. />
  114. </el-form-item>
  115. </el-col>
  116. </el-row>
  117. <el-row>
  118. <el-col :span="8">
  119. <el-form-item prop="teamId" label="项目团队">
  120. <el-select
  121. v-model="form.teamId"
  122. placeholder="请选择"
  123. style="width: 100%"
  124. :disabled="dialogType == 'view'"
  125. clearable
  126. @change="teamChange"
  127. >
  128. <el-option
  129. v-for="item in teamList"
  130. :key="item.id"
  131. :label="item.name"
  132. :value="item.id"
  133. >
  134. </el-option>
  135. </el-select>
  136. </el-form-item>
  137. </el-col>
  138. <el-col :span="8">
  139. <el-form-item label="项目预算" prop="budget">
  140. <el-row>
  141. <el-col :span="18">
  142. <el-input
  143. type="number"
  144. :min="0"
  145. v-model="form.budget"
  146. :disabled="dialogType == 'view'"
  147. >
  148. </el-input>
  149. </el-col>
  150. <el-col :span="6">
  151. <dict-selection
  152. dict-name="预算单位"
  153. v-model="form.unit"
  154. :disabled="dialogType == 'view'"
  155. ></dict-selection>
  156. </el-col>
  157. </el-row>
  158. </el-form-item>
  159. </el-col>
  160. <el-col :span="8">
  161. <el-form-item label="项目优先级">
  162. <dict-selection
  163. dict-name="项目优先级别"
  164. v-model="form.level"
  165. :disabled="dialogType == 'view'"
  166. ></dict-selection>
  167. </el-form-item>
  168. </el-col>
  169. </el-row>
  170. <el-row>
  171. <el-col :span="8">
  172. <el-form-item prop="planStartDate" label="计划开始日期">
  173. <el-date-picker
  174. @change="(val) => setCycleValue(val, 'planEndDate')"
  175. style="width: 100%"
  176. :disabled="dialogType == 'view'"
  177. v-model="form.planStartDate"
  178. value-format="yyyy-MM-dd"
  179. format="yyyy-MM-dd"
  180. :picker-options="{
  181. disabledDate: (time) => {
  182. return (
  183. form.planEndDate &&
  184. time.getTime() > new Date(form.planEndDate)
  185. );
  186. }
  187. }"
  188. type="date"
  189. placeholder="选择日期"
  190. >
  191. </el-date-picker>
  192. </el-form-item>
  193. </el-col>
  194. <el-col :span="8">
  195. <el-form-item prop="planEndDate" label="计划完成日期">
  196. <el-date-picker
  197. @change="(val) => setCycleValue(val, 'planStartDate')"
  198. style="width: 100%"
  199. :disabled="dialogType == 'view'"
  200. value-format="yyyy-MM-dd"
  201. format="yyyy-MM-dd"
  202. :picker-options="{
  203. disabledDate: (time) => {
  204. return (
  205. form.planStartDate &&
  206. time.getTime() < new Date(form.planStartDate)
  207. );
  208. }
  209. }"
  210. v-model="form.planEndDate"
  211. type="date"
  212. placeholder="选择日期"
  213. >
  214. </el-date-picker>
  215. </el-form-item>
  216. </el-col>
  217. <el-col :span="8">
  218. <el-form-item prop="cycle" label="项目周期">
  219. <el-input
  220. v-model="form.cycle"
  221. :disabled="dialogType == 'view'"
  222. ></el-input>
  223. </el-form-item>
  224. </el-col>
  225. <!-- <el-col :span="8">-->
  226. <!-- <el-form-item label="权重占比">-->
  227. <!-- <el-input type="number" :min="0" :max="100" v-model="form.proportion" :disabled="dialogType=='view'">-->
  228. <!-- <template slot="append">-->
  229. <!-- %-->
  230. <!-- </template>-->
  231. <!-- </el-input>-->
  232. <!-- </el-form-item>-->
  233. <!-- </el-col>-->
  234. </el-row>
  235. <el-row>
  236. <el-col :span="8">
  237. <el-form-item label="关联合同" prop="contractName">
  238. <el-input
  239. :disabled="dialogType == 'view'"
  240. clearable
  241. v-model="form.contractName"
  242. @click.native="handleContractBtn"
  243. />
  244. </el-form-item>
  245. </el-col>
  246. <el-col :span="8">
  247. <el-form-item label="客户名称">
  248. <el-input
  249. v-model="form.contactName"
  250. @click.native="handleGetCus"
  251. readonly
  252. :disabled="dialogType == 'view' || !!form.contractName"
  253. ></el-input>
  254. </el-form-item>
  255. </el-col>
  256. <el-col :span="8">
  257. <el-form-item label="联系人">
  258. <el-input v-model="form.contactRelationUserName"></el-input>
  259. <!-- <el-select
  260. v-model="form.contactRelationUserId"
  261. placeholder="请选择"
  262. @change="onchangeLink"
  263. style="width: 100%"
  264. :disabled="dialogType == 'view'"
  265. >
  266. <el-option
  267. v-for="item in linkNameOptions"
  268. :key="item.id"
  269. :label="item.linkName"
  270. :value="item.id"
  271. >
  272. </el-option>
  273. </el-select> -->
  274. </el-form-item>
  275. </el-col>
  276. <!-- <el-col :span="8">-->
  277. <!-- <el-form-item-->
  278. <!-- prop="stage"-->
  279. <!-- label="项目阶段">-->
  280. <!-- <el-input v-model="form.stage" :disabled="dialogType=='view'"></el-input>-->
  281. <!-- </el-form-item>-->
  282. <!-- </el-col>-->
  283. </el-row>
  284. <el-row>
  285. <el-col :span="8">
  286. <el-form-item prop="contactRelationPhone" label="客户联系电话">
  287. <el-input
  288. v-model="form.contactRelationPhone"
  289. :disabled="dialogType == 'view'"
  290. ></el-input>
  291. </el-form-item>
  292. </el-col>
  293. <el-col :span="16">
  294. <el-form-item label="联系地址" prop="contactAddressId">
  295. <el-cascader
  296. clearable
  297. v-model="form.contactAddressId"
  298. :options="cityData"
  299. ref="sendAddress"
  300. :disabled="dialogType == 'view'"
  301. style="width: 35%"
  302. ></el-cascader>
  303. <el-input
  304. placeholder="请输入"
  305. v-model="form.contactAddress"
  306. :disabled="dialogType == 'view'"
  307. style="width: 65%"
  308. ></el-input>
  309. </el-form-item>
  310. </el-col>
  311. </el-row>
  312. <el-row>
  313. <el-col :span="16">
  314. <el-form-item label="项目简介">
  315. <el-input
  316. type="textarea"
  317. :rows="2"
  318. v-model="form.content"
  319. :disabled="dialogType == 'view'"
  320. ></el-input>
  321. </el-form-item>
  322. </el-col>
  323. <el-col :span="8">
  324. <el-form-item label="附件">
  325. <fileUpload v-model="form.files" :type="dialogType"></fileUpload>
  326. <!-- <el-button type="primary" @click="handleUpload"> 上传</el-button>-->
  327. <!-- <fileUpload-->
  328. <!-- v-if="dialogType!='view'"-->
  329. <!-- style="position: absolute"-->
  330. <!-- v-model="form.files"-->
  331. <!-- module="main"-->
  332. <!-- :showLib="false"-->
  333. <!-- />-->
  334. <!-- <el-link-->
  335. <!-- v-else-->
  336. <!-- v-for="item in form.files"-->
  337. <!-- type="primary"-->
  338. <!-- :underline="false"-->
  339. <!-- @click="downloadFile(item)">-->
  340. <!-- {{ item.name }}-->
  341. <!-- </el-link>-->
  342. </el-form-item>
  343. </el-col>
  344. </el-row>
  345. <!-- <el-row>-->
  346. <!-- <el-col :span="24">-->
  347. <!-- <el-form-item label="备注">-->
  348. <!-- <el-input type="textarea" :rows="2" v-model="form.remark" :disabled="dialogType=='view'"></el-input>-->
  349. <!-- </el-form-item>-->
  350. <!-- </el-col>-->
  351. <!-- </el-row>-->
  352. </el-form>
  353. <custom-dialog
  354. v-if="customDialogFlag"
  355. ref="customRef"
  356. :customDialogFlag.sync="customDialogFlag"
  357. @getCusInfo="getCusInfo"
  358. ></custom-dialog>
  359. <contractListDialog
  360. ref="contractRef"
  361. v-if="contractDialogFlag"
  362. :contractDialogFlag.sync="contractDialogFlag"
  363. @changeParent="getContractInfo"
  364. ></contractListDialog>
  365. </div>
  366. </template>
  367. <script>
  368. import { getProjectCode, projectsToTreeAPI } from '@/api/project-manage';
  369. import PersonSelect from '@/components/CommomSelect/person-select.vue';
  370. import customDialog from '../../components/custom-dialog.vue';
  371. import fileUpload from '@/BIZComponents/addDoc/index.vue';
  372. import { getFile } from '@/api/system/file';
  373. import contractListDialog from '@/views/project-manage/components/contractListDialog.vue';
  374. import { getProduceTreeByCode } from '@/api/custom';
  375. import moment from 'moment';
  376. import { cityData } from 'ele-admin/packages/utils/regions';
  377. import { Link } from 'element-ui';
  378. import { contactDetail } from '@/api/eos';
  379. export default {
  380. name: 'project-form',
  381. components: { fileUpload, PersonSelect, customDialog, contractListDialog },
  382. props: {
  383. dialogType: {
  384. type: String,
  385. default: ''
  386. },
  387. dialogForm: {
  388. type: Object,
  389. default: () => {
  390. return {
  391. ...this.form
  392. };
  393. }
  394. },
  395. teamList: {
  396. type: Array,
  397. default: () => {
  398. return [];
  399. }
  400. },
  401. deptList: {
  402. type: Array,
  403. default: () => {
  404. return [];
  405. }
  406. },
  407. deptTreeList: {
  408. type: Array,
  409. default: () => {
  410. return [];
  411. }
  412. }
  413. },
  414. watch: {
  415. dialogForm: {
  416. handler(val) {
  417. this.form = { ...this.dialogForm };
  418. // 回显地址选择器
  419. if (
  420. this.form.contactAddressId &&
  421. this.form.contactAddressId.length > 0
  422. ) {
  423. this.form.contactAddressId = this.form.contactAddressId.split(',');
  424. }
  425. this.$nextTick(async () => {
  426. await this.getUserList(this.dialogForm.responsibleDeptId);
  427. });
  428. },
  429. deep: true
  430. }
  431. },
  432. data() {
  433. return {
  434. cityData,
  435. linkNameOptions: [],
  436. form: {
  437. budget: '',
  438. unit: '1',
  439. code: '',
  440. contactId: '',
  441. contactName: '',
  442. contactRelationPhone: '',
  443. contactRelationUserId: '',
  444. contactRelationUserName: '',
  445. content: '',
  446. cycle: '',
  447. deptUserId: '',
  448. deptUserName: '',
  449. level: '',
  450. monitorUserId: '',
  451. monitorUserName: '',
  452. planStartDate: '',
  453. planEndDate: '',
  454. proportion: undefined,
  455. name: '',
  456. parentId: '',
  457. remark: '',
  458. responsibleUserId: '',
  459. responsibleUserName: '',
  460. responsibleDeptId: '',
  461. responsibleDeptName: '',
  462. stage: '',
  463. teamId: '',
  464. teamName: '',
  465. type: '',
  466. contractId: '',
  467. contractName: '',
  468. files: []
  469. },
  470. typeTreeList: [],
  471. projectList: [],
  472. customDialogFlag: false,
  473. contractDialogFlag: false,
  474. rules: {
  475. type: {
  476. required: true,
  477. message: '请选择项目类型',
  478. trigger: 'change'
  479. },
  480. name: { required: true, message: '请输入项目名称', trigger: 'blur' },
  481. budget: {
  482. required: true,
  483. message: '请输入项目预算',
  484. trigger: 'blur'
  485. },
  486. contactName: {
  487. required: true,
  488. message: '请选择客户',
  489. trigger: 'blur'
  490. },
  491. teamId: {
  492. required: true,
  493. message: '请选择项目团队',
  494. trigger: 'change'
  495. },
  496. responsibleDeptId: {
  497. required: true,
  498. message: '请选择负责部门',
  499. trigger: 'change'
  500. },
  501. responsibleUserId: {
  502. required: true,
  503. message: '请选择项目经理',
  504. trigger: 'change'
  505. },
  506. planStartDate: {
  507. required: true,
  508. message: '请选择计划开始日期',
  509. trigger: 'change'
  510. },
  511. planEndDate: {
  512. required: true,
  513. message: '请选择计划完成日期',
  514. trigger: 'change'
  515. },
  516. code: {
  517. required: true,
  518. message: '请输入项目编码',
  519. trigger: ['blur', 'change']
  520. }
  521. }
  522. };
  523. },
  524. async created() {
  525. this.projectList = await projectsToTreeAPI({
  526. processStatus: '2',
  527. treeType: '0'
  528. });
  529. this.typeTreeList = await getProduceTreeByCode('XM1');
  530. },
  531. methods: {
  532. setCycleValue(val, prop) {
  533. if (!this.form[prop] || !val) return (this.form.cycle = '');
  534. const a = moment(this.form.planEndDate);
  535. const b = moment(this.form.planStartDate);
  536. this.form.cycle = a.diff(b, 'days') + 1 + ' 天'; // 1
  537. },
  538. async changeType(val) {
  539. // this.form.code = await getProjectCode(val)
  540. },
  541. async teamChange(val) {
  542. let find = this.teamList.find((e) => e.id == val) || {};
  543. this.form.teamName = find.name;
  544. this.$emit('teamChange', val);
  545. },
  546. // 选择负责人部门
  547. changeDeptInfo(id) {
  548. const info = this.deptList.find((e) => e.id == id) || {};
  549. this.form.responsibleDeptName = info.name;
  550. this.form.responsibleUserId = '';
  551. this.form.responsibleUserName = '';
  552. this.getUserList(id);
  553. },
  554. // 获取人员数据
  555. getUserList(groupId) {
  556. if (groupId) {
  557. this.$refs.directorRef && this.$refs.directorRef.getList({ groupId });
  558. }
  559. },
  560. handleContractBtn(e) {
  561. if (e.target.nodeName == 'I') {
  562. this.form = Object.assign({}, this.form, {
  563. contractName: '',
  564. contractId: '',
  565. contactId: '',
  566. contactName: '',
  567. contactRelationPhone: ''
  568. });
  569. return;
  570. }
  571. this.contractDialogFlag = true;
  572. },
  573. //选择合同信息回调
  574. getContractInfo(obj) {
  575. this.form.contractId = obj.id;
  576. this.form.contractName = obj.contractName;
  577. if (obj.type == 1) {
  578. this.form.contactId = obj.partaId;
  579. this.form.contactName = obj.partaName;
  580. this.getCusInfo({ id: obj.partaId });
  581. } else {
  582. this.form.contactId = obj.partbId;
  583. this.form.contactName = obj.partbName;
  584. this.getCusInfo({ id: obj.partbId });
  585. }
  586. },
  587. //获取客户信息
  588. handleGetCus() {
  589. this.customDialogFlag = true;
  590. let item = { id: this.form.contactId };
  591. this.$nextTick(() => {
  592. this.$refs.customRef.open(item);
  593. });
  594. },
  595. //选择客户信息回调
  596. async getCusInfo(obj) {
  597. const { base, other } = await contactDetail(obj.id);
  598. this.form = Object.assign({}, this.form, {
  599. contactId: base.id,
  600. contactName: base.name,
  601. contactRelationPhone:obj.linkPhone|| obj.phone,
  602. contactRelationUserName: obj.linkName
  603. });
  604. if (other.addressId) {
  605. this.form.contactAddressId =
  606. other.addressId && other.addressId.split(',');
  607. this.form.contactAddressName = other.addressName;
  608. this.form.contactAddress = other.address;
  609. } else if (base.addressId) {
  610. this.form.contactAddressId =
  611. base.addressId && base.addressId.split(',');
  612. this.form.contactAddressName = base.addressName;
  613. this.form.contactAddress = base.address;
  614. }
  615. },
  616. downloadFile(file) {
  617. getFile({ objectName: file.storePath }, file.type);
  618. },
  619. personChange(val, info) {
  620. this.form.responsibleUserName = info.name;
  621. },
  622. validForm() {
  623. return new Promise((resolve, reject) => {
  624. this.$refs.form.validate((valid) => {
  625. if (!valid) {
  626. this.$message.warning('有必填项未填,请检查');
  627. reject('有必填项未填,请检查');
  628. } else {
  629. // 基本信息处理
  630. if (this.$refs.sendAddress.getCheckedNodes()) {
  631. let node = this.$refs.sendAddress.getCheckedNodes()[0];
  632. if (node) {
  633. this.form.contactAddressId = node.path.join();
  634. this.form.contactAddressName = node.pathLabels.join();
  635. } else {
  636. this.form.contactAddressId = '';
  637. this.form.contactAddressName = '';
  638. }
  639. }
  640. resolve(this.form);
  641. }
  642. });
  643. });
  644. }
  645. }
  646. };
  647. </script>
  648. <style scoped lang="scss"></style>