edit.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. <template>
  2. <view>
  3. <view class="card-wrapper" v-if="showEdit()">
  4. <uni-card title="操作">
  5. <view class="editBtns" slot="actions">
  6. <view class="edit" v-if="!isDetail" @click="onClickProject">
  7. 项目详情
  8. </view>
  9. <view class="edit" v-if="canEdit(0)" @click="onEdit">编辑</view>
  10. <view class="edit" v-if="canEdit(0)" @click="onDelete">删除</view>
  11. <view class="edit" v-if="canEdit(0)" @click="onSubmitAuth">
  12. 提交审核
  13. </view>
  14. <view class="edit" v-if="canEdit(1)" @click="onMember">
  15. 成员管理
  16. </view>
  17. <view class="edit" v-if="canEdit(2)" @click="onExecute">
  18. 转执行
  19. </view>
  20. <view class="edit" v-if="canEdit(3)" @click="onWarranty">
  21. 转质保
  22. </view>
  23. <view class="edit" v-if="canEdit(3)" @click="onOperate">
  24. 转运营
  25. </view>
  26. <view class="edit" v-if="canAuth()" @click="onHandleAudit(1)">
  27. 审核通过
  28. </view>
  29. <view class="edit" v-if="canAuth()" @click="onHandleAudit(0)">
  30. 审核拒绝
  31. </view>
  32. </view>
  33. </uni-card>
  34. </view>
  35. <uni-popup ref="exePopup" type="dialog">
  36. <uni-popup-dialog
  37. title="转执行"
  38. type="info"
  39. @confirm="submitExecute"
  40. @close="onCancel"
  41. before-close
  42. >
  43. <uni-forms
  44. ref="exe"
  45. :modelValue="formData"
  46. label-position="left"
  47. :rules="exeRules"
  48. >
  49. <uni-forms-item required label="执行经理:" name="manager">
  50. <uni-data-picker
  51. class="depSelect"
  52. placeholder="请选择执行经理"
  53. :localdata="depUserTree"
  54. @change="changeManager"
  55. />
  56. </uni-forms-item>
  57. <uni-forms-item required label="合同状态:" name="contract">
  58. <picker
  59. @change="changeContract"
  60. :range="contracts"
  61. :value="formData.contract"
  62. >
  63. <view class="select">{{ contracts[formData.contract] }}</view>
  64. </picker>
  65. </uni-forms-item>
  66. </uni-forms>
  67. </uni-popup-dialog>
  68. </uni-popup>
  69. <uni-popup ref="wtyPopup" type="dialog">
  70. <uni-popup-dialog
  71. title="转质保"
  72. type="info"
  73. @confirm="submitWarranty"
  74. @close="onCancel"
  75. before-close
  76. >
  77. <uni-forms
  78. ref="wty"
  79. :modelValue="formData"
  80. label-position="left"
  81. :rules="wtyRules"
  82. >
  83. <uni-forms-item required label="质保经理:" name="manager">
  84. <uni-data-picker
  85. class="depSelect"
  86. placeholder="请选择质保经理"
  87. :localdata="depUserTree"
  88. @change="changeManager"
  89. />
  90. </uni-forms-item>
  91. </uni-forms>
  92. </uni-popup-dialog>
  93. </uni-popup>
  94. <uni-popup ref="optPopup" type="dialog">
  95. <uni-popup-dialog
  96. title="转运营"
  97. type="info"
  98. @confirm="submitOperate"
  99. @close="onCancel"
  100. before-close
  101. >
  102. <uni-forms
  103. ref="opt"
  104. :modelValue="formData"
  105. label-position="left"
  106. :rules="optRules"
  107. >
  108. <uni-forms-item required label="运营经理:" name="manager">
  109. <uni-data-picker
  110. class="depSelect"
  111. placeholder="请选择运营经理"
  112. :localdata="depUserTree"
  113. @change="changeManager"
  114. />
  115. </uni-forms-item>
  116. </uni-forms>
  117. </uni-popup-dialog>
  118. </uni-popup>
  119. </view>
  120. </template>
  121. <script>
  122. import { mapState } from "vuex";
  123. import {
  124. deleteApproval,
  125. submitAudit,
  126. startExecution,
  127. startWarranty,
  128. startOperate,
  129. authApproval,
  130. } from "@/services/project";
  131. export default {
  132. props: ["project", "user", "auth", "flowList", "depRole", "isDetail"],
  133. computed: {
  134. ...mapState(["depUserTree", "showSearch"]),
  135. },
  136. data() {
  137. return {
  138. contracts: ["无合同", "有合同"],
  139. formData: {
  140. manager: "",
  141. contract: null,
  142. },
  143. exeRules: {
  144. manager: {
  145. rules: [{ required: true, errorMessage: "请选择质保经理" }],
  146. },
  147. contract: {
  148. rules: [{ required: true, errorMessage: "请选择合同状态" }],
  149. },
  150. },
  151. wtyRules: {
  152. manager: {
  153. rules: [{ required: true, errorMessage: "请选择质保经理" }],
  154. },
  155. },
  156. optRules: {
  157. manager: {
  158. rules: [{ required: true, errorMessage: "请选择运营经理" }],
  159. },
  160. },
  161. };
  162. },
  163. methods: {
  164. showEdit() {
  165. return (
  166. !this.isDetail ||
  167. this.canEdit(0) ||
  168. this.canEdit(1) ||
  169. this.canEdit(2) ||
  170. this.canEdit(3) ||
  171. this.canAuth()
  172. );
  173. },
  174. hideHelper() {
  175. setTimeout(() => {
  176. uni.hideToast();
  177. if (this.isDetail) uni.navigateBack();
  178. else location.reload();
  179. }, 1800);
  180. },
  181. async onClickProject() {
  182. await this.$store.commit("setCurrentProject", this.project);
  183. uni.navigateTo({
  184. url: `./detail?id=${this.project.id}${this.auth ? "&auth=true" : ""}`,
  185. });
  186. },
  187. canEdit(index) {
  188. if (this.auth) return false;
  189. let {
  190. audit_status,
  191. project_status,
  192. author,
  193. LeaderId,
  194. opt_manager_id,
  195. wty_manager_id,
  196. } = this.project;
  197. //audit_status: 0未提审1审核中2审核拒绝3审核通过
  198. //project_status: 0售前1执行2转运营3转质保
  199. switch (index) {
  200. //编辑删除提审
  201. case 0:
  202. //售前阶段,未提审/审核被拒,创建人/管理员
  203. return (
  204. project_status == 0 &&
  205. (audit_status == 0 || audit_status == 2) &&
  206. (this.user.ID == author || this.user.IsSuper)
  207. );
  208. //成员管理
  209. case 1:
  210. //售前/执行/运营/质保,审核通过,项目经理/管理员
  211. let manager;
  212. switch (project_status) {
  213. case 0:
  214. manager = this.user.ID == author;
  215. break;
  216. case 1:
  217. manager = this.user.ID == LeaderId;
  218. break;
  219. case 2:
  220. manager =
  221. this.user.ID == LeaderId || this.user.ID == opt_manager_id;
  222. break;
  223. case 3:
  224. manager =
  225. this.user.ID == LeaderId || this.user.ID == wty_manager_id;
  226. break;
  227. }
  228. return audit_status == 3 && (manager || this.user.IsSuper);
  229. //转执行
  230. case 2:
  231. //售前,审核通过,售前经理/管理员
  232. return (
  233. project_status == 0 &&
  234. audit_status == 3 &&
  235. (this.user.ID == author || this.user.IsSuper)
  236. );
  237. //转质保运营
  238. case 3:
  239. //执行,审核通过,执行经理/管理员
  240. return (
  241. project_status == 1 &&
  242. audit_status == 3 &&
  243. (this.user.ID == LeaderId || this.user.IsSuper)
  244. );
  245. }
  246. },
  247. async onEdit() {
  248. await this.$store.commit("setCurrentProject", this.project);
  249. uni.navigateTo({
  250. url: `./add?project_id=${this.project.id}`,
  251. });
  252. },
  253. onDelete() {
  254. uni.showModal({
  255. title: "删除项目",
  256. content: "是否确认删除该项目",
  257. confirmText: "删除",
  258. confirmColor: "#ff7875",
  259. success: async (res) => {
  260. if (res.confirm) {
  261. await deleteApproval(this.project);
  262. uni.showToast({
  263. title: "删除成功",
  264. });
  265. this.hideHelper();
  266. }
  267. },
  268. });
  269. },
  270. onSubmitAuth() {
  271. uni.showModal({
  272. title: "提交审核",
  273. content: "是否确认提交审核",
  274. confirmText: "提审",
  275. success: async (res) => {
  276. if (res.confirm) {
  277. let payload = {
  278. id: this.project.id,
  279. flow_id: this.project.flow_id,
  280. node_id: this.project.node_id,
  281. };
  282. await submitAudit(payload);
  283. uni.showToast({
  284. title: "提审成功",
  285. });
  286. this.hideHelper();
  287. }
  288. },
  289. });
  290. },
  291. async onMember() {
  292. await this.$store.commit("setCurrentProject", this.project);
  293. uni.navigateTo({
  294. url: "./member",
  295. });
  296. },
  297. changeManager(e) {
  298. if (e.detail.value.length > 0)
  299. this.formData.manager = e.detail.value[e.detail.value.length - 1].value;
  300. else this.formData.manager = "";
  301. },
  302. async onExecute() {
  303. await this.$store.commit("setShowSearch", false);
  304. this.$refs.exePopup.open();
  305. },
  306. changeContract(e) {
  307. this.formData.contract = e.detail.value;
  308. },
  309. async submitHelper(payload = {}, type) {
  310. const [dep_id, manager_id] = this.formData.manager.split("-");
  311. payload = {
  312. ...payload,
  313. project_code_id: this.project.id,
  314. dep_id: Number(dep_id),
  315. };
  316. switch (type) {
  317. case "exe":
  318. await startExecution(payload);
  319. this.$refs.exePopup.close();
  320. uni.showToast({
  321. title: "转执行送审成功",
  322. });
  323. break;
  324. case "wty":
  325. await startWarranty(payload);
  326. this.$refs.wtyPopup.close();
  327. uni.showToast({
  328. title: "转质保送审成功",
  329. });
  330. break;
  331. case "opt":
  332. await startOperate(payload);
  333. this.$refs.optPopup.close();
  334. uni.showToast({
  335. title: "转运营送审成功",
  336. });
  337. break;
  338. }
  339. this.hideHelper();
  340. },
  341. submitExecute() {
  342. this.$refs.exe.validate((err) => {
  343. if (!err) {
  344. const [dep_id, manager_id] = this.formData.manager.split("-");
  345. let payload = {
  346. with_contract: Number(this.formData.contract),
  347. exe_manager_id: Number(manager_id),
  348. };
  349. this.submitHelper(payload, "exe");
  350. }
  351. });
  352. },
  353. async onWarranty() {
  354. await this.$store.commit("setShowSearch", false);
  355. this.$refs.wtyPopup.open();
  356. },
  357. submitWarranty() {
  358. this.$refs.wty.validate((err) => {
  359. if (!err) {
  360. const [dep_id, manager_id] = this.formData.manager.split("-");
  361. let payload = {
  362. wty_manager_id: Number(manager_id),
  363. };
  364. this.submitHelper(payload, "wty");
  365. }
  366. });
  367. },
  368. async onOperate() {
  369. await this.$store.commit("setShowSearch", false);
  370. this.$refs.optPopup.open();
  371. },
  372. submitOperate() {
  373. this.$refs.opt.validate((err) => {
  374. if (!err) {
  375. const [dep_id, manager_id] = this.formData.manager.split("-");
  376. let payload = {
  377. opt_manager_id: Number(manager_id),
  378. };
  379. this.submitHelper(payload, "opt");
  380. }
  381. });
  382. },
  383. async onCancel() {
  384. await this.$store.commit("setShowSearch", true);
  385. this.$refs.exePopup.close();
  386. this.$refs.wtyPopup.close();
  387. this.$refs.optPopup.close();
  388. this.formData = {
  389. manager: "",
  390. contract: null,
  391. };
  392. },
  393. canAuth() {
  394. if (!this.auth) return false;
  395. let { NodeInfo, audit_status, project_status } = this.project;
  396. if (!NodeInfo || this.flowList.length == 0 || this.depRole.length == 0)
  397. return false;
  398. if (audit_status != 1) return false;
  399. if (project_status == 2)
  400. return this.project.opt_manager_id == this.user.ID;
  401. if (project_status == 3)
  402. return this.project.wty_manager_id == this.user.ID;
  403. let flow = this.flowList.find((item) => item.id == NodeInfo.flow_id);
  404. if (!flow) return false;
  405. let { NodeAudits } = flow.Nodes.find((item) => item.id == NodeInfo.id);
  406. const role = this.depRole.find((item) =>
  407. NodeAudits.find((audit) => audit.audit_role == item.ID)
  408. );
  409. return Boolean(role);
  410. },
  411. onHandleAudit(value) {
  412. if (value) {
  413. uni.showModal({
  414. title: "审批通过",
  415. content: "是否确认通过审批",
  416. confirmText: "通过",
  417. success: async (res) => {
  418. if (res.confirm) {
  419. let payload = {
  420. id: this.project.id,
  421. project_full_code: this.project.project_full_code,
  422. flow_id: this.project.flow_id,
  423. node_id: this.project.node_id,
  424. audit_status: 3,
  425. audit_comment: "",
  426. };
  427. await authApproval(payload);
  428. uni.showToast({
  429. title: "审核成功",
  430. });
  431. this.hideHelper();
  432. }
  433. },
  434. });
  435. } else {
  436. uni.showModal({
  437. title: "是否确认拒绝",
  438. content: "拒绝理由",
  439. editable: true,
  440. success: async (res) => {
  441. if (res.confirm) {
  442. let payload = {
  443. id: this.project.id,
  444. project_full_code: this.project.project_full_code,
  445. flow_id: this.project.flow_id,
  446. node_id: this.project.node_id,
  447. audit_status: 2,
  448. audit_comment: res.content,
  449. };
  450. await authApproval(payload);
  451. uni.showToast({
  452. title: "已拒绝",
  453. });
  454. this.hideHelper();
  455. }
  456. },
  457. });
  458. }
  459. },
  460. },
  461. };
  462. </script>
  463. <style lang="less" scoped>
  464. .editBtns {
  465. display: flex;
  466. justify-content: space-around;
  467. flex-wrap: wrap;
  468. margin: 0 5%;
  469. .edit {
  470. width: 30%;
  471. margin-bottom: 20px;
  472. font-size: 28rpx;
  473. text-align: center;
  474. }
  475. }
  476. .card-wrapper {
  477. padding-bottom: 60rpx;
  478. }
  479. .select {
  480. width: 100%;
  481. height: 72rpx;
  482. line-height: 70rpx;
  483. border: 1px solid #666;
  484. padding-left: 20rpx;
  485. }
  486. ::v-deep {
  487. .uni-steps__column-title {
  488. font-size: 18px;
  489. line-height: 24px;
  490. }
  491. .uni-steps__column-desc {
  492. font-size: 14px;
  493. line-height: 18px;
  494. }
  495. }
  496. .depSelect {
  497. width: 200px;
  498. }
  499. </style>