index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. <template>
  2. <div class="cost-audit-management">
  3. <!-- 成本审核项目列表页面 -->
  4. <div class="audit-list-container">
  5. <div class="search-section">
  6. <el-input
  7. v-model="searchQuery"
  8. placeholder="监审项目名称"
  9. style="width: 300px; margin-right: 10px"
  10. clearable
  11. />
  12. <el-button type="primary" @click="handleSearch">查询</el-button>
  13. </div>
  14. <el-table
  15. v-loading="loading"
  16. class="mb10"
  17. :data="auditProjectList"
  18. style="width: 100%"
  19. border
  20. default-expand-all
  21. row-key="id"
  22. :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
  23. >
  24. <el-table-column
  25. type="index"
  26. label="序号"
  27. width="80"
  28. header-align="center"
  29. align="center"
  30. >
  31. <template slot-scope="scope">
  32. <!-- 只显示父节点的序号 -->
  33. <span v-if="scope.row.children">
  34. {{ getParentNodeIndex(scope.row) }}
  35. </span>
  36. <span v-else></span>
  37. </template>
  38. </el-table-column>
  39. <el-table-column
  40. prop="projectName"
  41. label="成本监审项目名称"
  42. show-overflow-tooltip
  43. header-align="center"
  44. align="left"
  45. />
  46. <el-table-column
  47. prop="auditObject"
  48. label="监审对象"
  49. header-align="center"
  50. align="left"
  51. />
  52. <el-table-column
  53. prop="auditPeriod"
  54. label="监审期间"
  55. header-align="center"
  56. align="center"
  57. width="120"
  58. />
  59. <el-table-column
  60. prop="source"
  61. label="立项来源"
  62. header-align="center"
  63. align="center"
  64. width="100"
  65. />
  66. <el-table-column
  67. prop="form"
  68. label="监审形式"
  69. header-align="center"
  70. align="center"
  71. width="100"
  72. />
  73. <el-table-column
  74. prop="currentNodeName"
  75. label="状态"
  76. align="center"
  77. width="150"
  78. >
  79. <template slot-scope="scope">
  80. <span v-if="!scope.row.isSubTask">
  81. <span>
  82. {{ scope.row.currentNodeName }}-{{ scope.row.statusName }}
  83. </span>
  84. </span>
  85. <span v-else>{{ scope.row.statusName }}</span>
  86. </template>
  87. </el-table-column>
  88. <el-table-column label="操作" align="center" width="260">
  89. <template slot-scope="scope">
  90. <span v-if="!scope.row.isSubTask" class="action-buttons">
  91. <el-button type="text" @click="handleViewTaskDetail(scope.row)">
  92. 任务详情
  93. </el-button>
  94. <el-button type="text" @click="handleOpenMainDetails(scope.row)">
  95. 任务办理
  96. </el-button>
  97. <el-button type="text" @click="handleCheckRecord(scope.row)">
  98. 备忘录
  99. </el-button>
  100. </span>
  101. <span v-if="scope.row.isSubTask" class="action-buttons">
  102. <el-button
  103. v-if="
  104. scope.row.currentNode === 'clcs' &&
  105. (scope.row.status === '200' || scope.row.status === '600')
  106. "
  107. type="text"
  108. @click="handleOpenDetails(scope.row)"
  109. >
  110. 资料初审
  111. </el-button>
  112. <el-button
  113. v-if="
  114. (scope.row.currentNode === 'sdsh' ||
  115. scope.row.currentNode === 'yjfk') &&
  116. scope.row.status === '200'
  117. "
  118. type="text"
  119. @click="handleOpenDetails(scope.row)"
  120. >
  121. 成本审核
  122. </el-button>
  123. <el-button
  124. v-if="
  125. scope.row.currentNode === 'yjgz' && scope.row.status === '200'
  126. "
  127. type="text"
  128. @click="handleOpenDetails(scope.row)"
  129. >
  130. 意见告知
  131. </el-button>
  132. <el-button
  133. v-if="
  134. scope.row.currentNode === 'yjfk' && scope.row.status === '260'
  135. "
  136. type="text"
  137. @click="handleOpenDetails(scope.row)"
  138. >
  139. 审核
  140. </el-button>
  141. <el-button
  142. v-if="scope.row.status === '300'"
  143. type="text"
  144. @click="handleHf(scope.row)"
  145. >
  146. 恢复
  147. </el-button>
  148. <el-button
  149. type="text"
  150. @click="handleMessage(scope.row, 'chengben')"
  151. >
  152. 查看
  153. </el-button>
  154. </span>
  155. </template>
  156. </el-table-column>
  157. </el-table>
  158. <el-pagination
  159. background
  160. layout="total, sizes, prev, pager, next"
  161. :current-page="currentPage"
  162. :page-sizes="[10, 20, 30, 40]"
  163. :page-size="pageSize"
  164. :total="total"
  165. @current-change="handleCurrentChange"
  166. @size-change="handleSizeChange"
  167. />
  168. </div>
  169. <!-- 详情弹窗组件 -->
  170. <details-dialog
  171. :id="selectedProject && selectedProject.id"
  172. ref="detailsRef"
  173. :selected-project="selectedProject"
  174. :visible.sync="detailsVisible"
  175. :current-node="selectedProject && selectedProject.currentNode"
  176. :current-status="selectedProject && selectedProject.status"
  177. @close="handleDetailsClose"
  178. @refresh="handleRefresh"
  179. />
  180. <!-- 主详情弹窗组件 -->
  181. <mainDetailsDialog
  182. :id="selectedProject && selectedProject.id"
  183. ref="mainDetailsRef"
  184. :visible.sync="mainDetailsVisible"
  185. :current-node="selectedProject && selectedProject.currentNode"
  186. :current-status="selectedProject && selectedProject.status"
  187. @close="handleMainDetailsClose"
  188. @refresh="handleMainRefresh"
  189. />
  190. <taskInfo ref="taskInfo" />
  191. <!-- 成本监审信息弹窗 -->
  192. <cbjs-info
  193. :id="cbjsInfoData && cbjsInfoData.id"
  194. :selected-project="selectedProject"
  195. :visible.sync="cbjsInfoVisible"
  196. :current-node="cbjsInfoData && cbjsInfoData.currentNode"
  197. :current-status="cbjsInfoData && cbjsInfoData.status"
  198. />
  199. <taskDetail ref="taskDetail" />
  200. </div>
  201. </template>
  202. <script>
  203. import { doProcessBtn } from '@/api/dataPreliminaryReview'
  204. import detailsDialog from './details.vue'
  205. import mainDetailsDialog from './mainDetails.vue'
  206. // 成本监审任务列表API
  207. import { getReviewTaskList } from '@/api/audit/auditIndex'
  208. import taskInfo from '@/components/task/taskInfo.vue'
  209. import cbjsInfo from '@/components/task/cbjsInfo.vue'
  210. import taskDetail from '@/components/task/taskDetail.vue'
  211. export default {
  212. name: 'CostAuditManagement',
  213. components: {
  214. detailsDialog,
  215. taskInfo,
  216. cbjsInfo,
  217. mainDetailsDialog,
  218. taskDetail,
  219. },
  220. data() {
  221. return {
  222. // 分页相关
  223. currentPage: 1,
  224. pageSize: 10,
  225. total: 0,
  226. // 搜索相关
  227. searchQuery: '',
  228. // 列表数据
  229. auditProjectList: [],
  230. // 加载状态
  231. loading: false,
  232. // 详情弹窗相关
  233. detailsVisible: false,
  234. selectedProject: null,
  235. // cbjsInfo弹窗相关
  236. cbjsInfoVisible: false,
  237. cbjsInfoData: null,
  238. mainDetailsVisible: false,
  239. }
  240. },
  241. created() {
  242. this.loadAuditProjectList()
  243. },
  244. methods: {
  245. // 获取父节点的连续序号
  246. getParentNodeIndex(row) {
  247. // 过滤出所有父节点
  248. const parentNodes = this.auditProjectList.filter(
  249. (item) => item.children && item.children.length > 0
  250. )
  251. // 找到当前行在父节点数组中的索引
  252. const index = parentNodes.findIndex((item) => item.id === row.id)
  253. // 返回序号(索引+1)
  254. return index + 1
  255. },
  256. // 加载审核项目列表
  257. async loadAuditProjectList() {
  258. try {
  259. this.loading = true
  260. // 调用API获取数据
  261. const params = {
  262. currentPage: this.currentPage,
  263. pageSize: this.pageSize,
  264. projectName: this.searchQuery,
  265. }
  266. const response = await getReviewTaskList(params)
  267. // 根据API返回格式处理数据
  268. if (response.state && response.value) {
  269. // 获取记录列表
  270. const records = response.value.records || []
  271. // 转换数据格式,将childTasks转换为children以适应表格组件
  272. this.auditProjectList = records.map((record) => {
  273. return {
  274. id: record.id,
  275. projectName: record.projectName,
  276. auditObject: record.auditedUnitName,
  277. auditPeriod: record.auditPeriod,
  278. source: this.getSourceTypeText(record.sourceType),
  279. form: this.getAuditTypeText(record.auditType),
  280. status: this.getStatusText(record.status),
  281. statusName: record.statusName,
  282. isSubTask: record.pid !== '0',
  283. currentNodeName: record.currentNodeName,
  284. currentNode: record.currentNode,
  285. projectId: record.projectId,
  286. auditedUnitId: record.auditedUnitId,
  287. children: record.childTasks
  288. ? record.childTasks.map((child) => ({
  289. id: child.id,
  290. projectName: child.projectName,
  291. auditObject: child.auditedUnitName,
  292. auditPeriod: record.auditPeriod, // 子任务可能使用父任务的审核期间
  293. source: '',
  294. form: '',
  295. currentNode: child.currentNode,
  296. status: child.status,
  297. statusName: child.statusName,
  298. isSubTask: true,
  299. projectId: child.projectId,
  300. auditedUnitId: child.auditedUnitId,
  301. taskId: child.id,
  302. }))
  303. : [],
  304. }
  305. })
  306. // 设置总数
  307. this.total = response.value.total || 0
  308. } else {
  309. this.auditProjectList = []
  310. this.total = 0
  311. this.$message.warning('未获取到审核项目数据')
  312. }
  313. } catch (error) {
  314. this.$message.error('加载审核项目列表失败')
  315. console.error('加载审核项目列表失败:', error)
  316. } finally {
  317. this.loading = false
  318. }
  319. },
  320. // 获取来源类型文本
  321. getSourceTypeText(type) {
  322. const typeMap = {
  323. 1: '年度计划内',
  324. 2: '年度计划外',
  325. // 可根据实际需求补充其他类型
  326. }
  327. return typeMap[type] || type
  328. },
  329. // 获取审核类型文本
  330. getAuditTypeText(type) {
  331. const typeMap = {
  332. 1: '定期监审',
  333. 2: '定调价监审',
  334. // 可根据实际需求补充其他类型
  335. }
  336. return typeMap[type] || type
  337. },
  338. // 获取状态文本
  339. getStatusText(status) {
  340. const statusMap = {
  341. ccls: '资料初审',
  342. 200: '审核通过',
  343. clcs: '审核中', // 添加clcs状态映射为审核中
  344. // 可根据实际需求补充其他状态
  345. }
  346. return statusMap[status] || status
  347. },
  348. // 搜索
  349. handleSearch() {
  350. // 搜索逻辑
  351. this.loadAuditProjectList()
  352. },
  353. // 查看任务详情
  354. handleViewTaskDetail(row) {
  355. // this.selectedTask = row
  356. // this.activeTab = 'detail'
  357. // this.showTaskDetail = true
  358. this.$refs.taskDetail.open(row, 'chengben')
  359. },
  360. // 打开详情弹窗
  361. handleOpenDetails(project) {
  362. console.log('project', project)
  363. this.selectedProject = project
  364. this.detailsVisible = true
  365. },
  366. handleOpenMainDetails(project) {
  367. console.log('project', project)
  368. this.selectedProject = project
  369. this.mainDetailsVisible = true
  370. },
  371. // 详情弹窗关闭处理
  372. handleDetailsClose() {
  373. this.selectedProject = null
  374. this.detailsVisible = false
  375. // 可以在这里添加刷新列表的逻辑
  376. },
  377. // 刷新表格数据
  378. handleRefresh() {
  379. // 刷新列表数据
  380. this.loadAuditProjectList()
  381. },
  382. // 主详情弹窗关闭处理
  383. handleMainDetailsClose() {
  384. this.selectedProject = null
  385. this.mainDetailsVisible = false
  386. },
  387. // 主详情刷新处理
  388. handleMainRefresh() {
  389. // 刷新列表数据
  390. this.loadAuditProjectList()
  391. },
  392. // 查记录
  393. handleCheckRecord(project) {
  394. // memoManage
  395. this.$router.push({
  396. name: 'memoManage',
  397. // params: { projectId: project.id }
  398. })
  399. },
  400. // 恢复任务
  401. async handleHf(row) {
  402. if (!row || !row.id) {
  403. this.$message.error('缺少任务ID')
  404. return
  405. }
  406. // 弹出确认对话框
  407. this.$confirm('确定要恢复此任务吗?', '恢复任务', {
  408. confirmButtonText: '确定',
  409. cancelButtonText: '取消',
  410. type: 'warning',
  411. })
  412. .then(async () => {
  413. try {
  414. const params = {
  415. taskId: row.id,
  416. key: 2,
  417. status: 200,
  418. processNodeKey: row.currentNode,
  419. }
  420. const response = await doProcessBtn(params)
  421. if (response && response.code === 200) {
  422. this.$message.success('恢复任务成功')
  423. // 刷新列表
  424. this.loadAuditProjectList()
  425. } else {
  426. this.$message.error(response?.message || '恢复任务失败')
  427. }
  428. } catch (error) {
  429. this.$message.error('恢复任务失败')
  430. console.error('恢复任务失败:', error)
  431. }
  432. })
  433. .catch(() => {
  434. // 用户取消操作
  435. this.$message.info('已取消恢复任务')
  436. })
  437. },
  438. // 分页处理
  439. handleSizeChange(size) {
  440. this.pageSize = size
  441. this.loadAuditProjectList()
  442. },
  443. handleCurrentChange(current) {
  444. this.currentPage = current
  445. this.loadAuditProjectList()
  446. },
  447. // 查看 - 修改为打开cbjsInfo弹窗
  448. handleMessage(row, type) {
  449. if (type === 'chengben') {
  450. this.cbjsInfoData = row
  451. this.cbjsInfoVisible = true
  452. } else {
  453. this.$refs.taskInfo.open(row, type)
  454. }
  455. },
  456. },
  457. }
  458. </script>
  459. <style scoped>
  460. .cost-audit-management {
  461. padding: 20px;
  462. }
  463. /* 列表页面样式 */
  464. .search-section {
  465. margin-bottom: 20px;
  466. }
  467. .action-buttons {
  468. font-size: 12px;
  469. }
  470. .action-buttons a {
  471. color: #409eff;
  472. text-decoration: none;
  473. }
  474. .separator {
  475. margin: 0 5px;
  476. color: #999;
  477. }
  478. .note-section {
  479. margin-top: 20px;
  480. }
  481. .note-text {
  482. color: #f56c6c;
  483. font-size: 12px;
  484. margin: 5px 0;
  485. }
  486. /* 详情页面样式 */
  487. .audit-detail-container {
  488. margin-top: 20px;
  489. }
  490. .detail-form {
  491. margin-top: 20px;
  492. }
  493. .tab-content {
  494. padding: 20px;
  495. background-color: #f9f9f9;
  496. min-height: 200px;
  497. }
  498. /* 办理页面样式 */
  499. .audit-process-container {
  500. margin-top: 20px;
  501. }
  502. .process-actions {
  503. margin-bottom: 20px;
  504. }
  505. .process-actions .el-button {
  506. margin-right: 10px;
  507. }
  508. /* 响应式设计 */
  509. @media (max-width: 768px) {
  510. .process-steps {
  511. flex-direction: column;
  512. }
  513. .step-line {
  514. width: 2px;
  515. height: 20px;
  516. margin: 5px 0;
  517. }
  518. .documents-layout {
  519. flex-direction: column;
  520. }
  521. .documents-type-list {
  522. width: 100%;
  523. margin-right: 0;
  524. margin-bottom: 20px;
  525. }
  526. .meeting-form .el-row {
  527. flex-direction: column;
  528. }
  529. .meeting-form .el-col {
  530. width: 100%;
  531. }
  532. }
  533. </style>