detailed.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. <template>
  2. <HeadPanl class="project-detail-header">
  3. <div class="meta">
  4. <div class="header">
  5. <h3>{{ project?.projectName }}</h3>
  6. <div
  7. v-if="project?.projectStatus === ProjectStatus.undone"
  8. class="actions"
  9. >
  10. <a-button @click="updateProject">修改项目</a-button>
  11. <a-button @click="deleteProject">删除项目</a-button>
  12. <a-button type="primary" @click="finishProject"> 完成项目 </a-button>
  13. </div>
  14. </div>
  15. <div class="body">
  16. <div class="info">
  17. <div class="meta">
  18. <p><span>创建人</span>{{ project?.projectCreater }}</p>
  19. <p><span>创建时间</span>{{ project?.createTime }}</p>
  20. <p><span>更新时间</span>{{ project?.updateTime }}</p>
  21. </div>
  22. <p class="desc">{{ project?.projectMsg }}</p>
  23. </div>
  24. <!-- <Simples :data="simples" /> -->
  25. </div>
  26. <a-tabs :active-key="activeTabName" @change="changeTab">
  27. <a-tab-pane
  28. v-for="option in tabOptions"
  29. :key="option.key"
  30. :tab="option.label"
  31. />
  32. </a-tabs>
  33. </div>
  34. </HeadPanl>
  35. <BodyPanl>
  36. <RouterView v-slot="{ Component }">
  37. <KeepAlive>
  38. <component :is="Component" />
  39. </KeepAlive>
  40. </RouterView>
  41. </BodyPanl>
  42. </template>
  43. <script setup lang="ts">
  44. import Simples from '@/components/simples/index.vue'
  45. import EditProject from './edit.vue'
  46. import { Modal } from 'ant-design-vue'
  47. import { HeadPanl, BodyPanl } from '@/layout/panl'
  48. import { router, RoutesName, routesMetas } from '@/router'
  49. import { computed, onActivated, onDeactivated, toRef } from 'vue'
  50. import { useProject, ProjectStatus } from '@/store'
  51. import { useRealtime } from '@/hook'
  52. import { renderModal } from '@/helper'
  53. import { uploadFile } from '@/api'
  54. const simples = computed(() => [
  55. { label: '信息', value: 2 },
  56. { label: '待处理', value: 2 },
  57. { label: '已解决', value: 2 },
  58. { label: '未解决', value: 2 },
  59. { label: '进行中', value: 2 }
  60. ])
  61. const tabOptions = [
  62. // RoutesName.projectMaterial,
  63. RoutesName.projectScenes,
  64. RoutesName.projectMembers
  65. ].map(name => ({
  66. key: name,
  67. label: routesMetas[name].title
  68. }))
  69. const activeTabName = computed(
  70. () => router.currentRoute.value.name as RoutesName
  71. )
  72. const changeTab = (name: any) => {
  73. router.replace({ name, params: router.currentRoute.value.params })
  74. }
  75. const projectStore = useProject()
  76. const project = toRef(projectStore.$state, 'current')
  77. useRealtime(() => {
  78. const id = Number(router.currentRoute.value.params.id)
  79. const back = () => router.back()
  80. if (!id || id < 0) {
  81. back()
  82. throw '错误页面'
  83. }
  84. return projectStore.setCurrent(id).catch(back)
  85. })
  86. let interval: number
  87. onActivated(() => {
  88. interval = setInterval(() => {
  89. const id = Number(router.currentRoute.value.params.id)
  90. id && projectStore.setCurrent(id)
  91. }, 1000)
  92. })
  93. onDeactivated(() => {
  94. clearInterval(interval)
  95. })
  96. const deleteProject = () => {
  97. Modal.confirm({
  98. content: '删除后无法恢复,是否确认?',
  99. title: '删除项目',
  100. width: '400px',
  101. okText: '删除',
  102. icon: null,
  103. cancelText: '取消',
  104. onOk: async () => {
  105. await projectStore.delete()
  106. router.replace({ name: RoutesName.projects })
  107. }
  108. })
  109. }
  110. const finishProject = async () => {
  111. await projectStore.finish()
  112. router.replace({ name: RoutesName.projects })
  113. }
  114. const updateProject = async () => {
  115. renderModal(EditProject, {
  116. project: projectStore.current!,
  117. async onSave({ projectImg, bimFile, ...data }) {
  118. const img =
  119. projectImg && typeof projectImg !== 'string'
  120. ? await uploadFile(projectImg as File)
  121. : projectImg
  122. await projectStore.update({ ...data, projectImg: img })
  123. }
  124. })
  125. }
  126. </script>
  127. <style lang="scss" scoped>
  128. .project-detail-header {
  129. padding-bottom: 0;
  130. }
  131. .header {
  132. display: flex;
  133. justify-content: space-between;
  134. margin-bottom: 24px;
  135. align-items: center;
  136. h3 {
  137. font-size: 20px;
  138. color: #323233;
  139. margin: 0;
  140. }
  141. .actions button {
  142. margin-left: 16px;
  143. }
  144. }
  145. .body {
  146. display: flex;
  147. justify-content: space-between;
  148. .meta {
  149. display: flex;
  150. margin-bottom: 16px;
  151. p {
  152. color: #888888;
  153. margin-right: 20px;
  154. margin-bottom: 0;
  155. span {
  156. color: #323233;
  157. margin-right: 3px;
  158. &::after {
  159. content: ':';
  160. }
  161. }
  162. }
  163. }
  164. .desc {
  165. flex: 1;
  166. max-width: 800px;
  167. padding: 14px 10px;
  168. background: #fafafa;
  169. color: #646566;
  170. line-height: 20px;
  171. font-size: 14px;
  172. }
  173. .tabs {
  174. margin-top: 16px;
  175. }
  176. }
  177. </style>
  178. <style lang="scss">
  179. .project-detail-header .ant-tabs-top > .ant-tabs-nav {
  180. margin: 0;
  181. }
  182. </style>