AchWorkForm.vue 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <template>
  2. <view class="document-form">
  3. <uv-loading-icon
  4. v-if="loading"
  5. mode="circle"
  6. text="正在加载学术著作详情..."
  7. ></uv-loading-icon>
  8. <template v-else-if="form">
  9. <!-- 基本信息 -->
  10. <CommonSection title="基本信息" :isFirst="true">
  11. <CommonInfoRow label="著作名称" :value="form.workName" />
  12. <CommonInfoRow
  13. label="著作类别"
  14. :value="getDictLabel('sci_work_class', form.workClass)"
  15. />
  16. <CommonInfoRow label="出版单位" :value="form.workPublisher" />
  17. <CommonInfoRow
  18. label="出版社类型"
  19. :value="
  20. getDictLabel('sci_work_publisherType', form.workPublisherType)
  21. "
  22. />
  23. <CommonInfoRow
  24. label="出版时间"
  25. :value="formatDate(form.workPublicationDate)"
  26. />
  27. <CommonInfoRow label="所属部门" :value="form.deptName" />
  28. <CommonInfoRow label="CIP号" :value="form.cip" />
  29. <CommonInfoRow label="字数" :value="form.wordsNum" />
  30. <CommonInfoRow
  31. label="所属年份"
  32. :value="
  33. form.statisticalYear
  34. ? formatDate(form.statisticalYear, 'YYYY')
  35. : '-'
  36. "
  37. />
  38. <CommonInfoRow
  39. label="是否国家规范化教材"
  40. :value="form.isStandard === '10' ? '是' : '否'"
  41. />
  42. <CommonInfoRow
  43. label="是否翻译著作"
  44. :value="form.isTranslation === '10' ? '是' : '否'"
  45. />
  46. <CommonInfoRow label="著作附件(封面和版权页)" isColumn>
  47. <view class="file-links">
  48. <template v-if="workFileList.length > 0">
  49. <view
  50. class="file-item"
  51. v-for="(item, index) in workFileList"
  52. :key="'work-file-' + index"
  53. @click="handlePreview(item)"
  54. >
  55. <text class="file-link">{{
  56. item.fileName || item.name || "-"
  57. }}</text>
  58. </view>
  59. </template>
  60. <text v-else>-</text>
  61. </view>
  62. </CommonInfoRow>
  63. <CommonInfoRow label="所属平台" isColumn>
  64. <view class="platform-tags">
  65. <template v-if="platformList.length > 0">
  66. <uv-tags
  67. v-for="(p, index) in platformList"
  68. :key="index"
  69. :text="
  70. p.platformName === '其他'
  71. ? '其他'
  72. : p.platformType
  73. ? p.platformName + ' (' + p.platformType + ')'
  74. : p.platformName
  75. "
  76. type="primary"
  77. plain
  78. size="mini"
  79. class="mr5"
  80. ></uv-tags>
  81. </template>
  82. <text v-else>-</text>
  83. </view>
  84. </CommonInfoRow>
  85. <CommonInfoRow label="所属团队" :value="form.belongTeam || '-'" />
  86. </CommonSection>
  87. <!-- 关联项目 -->
  88. <CommonSection title="关联项目" v-if="form.projList?.length">
  89. <view
  90. class="achievement-card"
  91. v-for="(row, index) in form.projList"
  92. :key="index"
  93. >
  94. <view class="a-row">
  95. <text class="al">关联类型:</text>
  96. <text class="av">{{
  97. row.sourceType === "10" ? "项目" : "学科"
  98. }}</text>
  99. </view>
  100. <view class="a-row">
  101. <text class="al">项目/学科:</text>
  102. <text class="av">{{ row.projectSource || "-" }}</text>
  103. </view>
  104. </view>
  105. </CommonSection>
  106. <!-- 著作人 -->
  107. <CommonSection title="著作人信息" v-if="form.memberList?.length">
  108. <view class="member-list">
  109. <view
  110. class="member-item"
  111. v-for="(row, index) in form.memberList"
  112. :key="index"
  113. >
  114. <view class="member-header">
  115. <view class="m-left">
  116. <text class="m-name mr20">{{ row.memberName }}</text>
  117. <text class="m-tag" v-if="row.roleContent">{{
  118. getDictLabel("sci_work_roleContent", row.roleContent)
  119. }}</text>
  120. </view>
  121. <text class="m-tag blue" v-if="row.position"
  122. >第{{ row.position }}位</text
  123. >
  124. </view>
  125. <view class="m-body">
  126. <view class="m-line"
  127. ><text class="l">贡献率:</text
  128. ><text class="v">{{ row.contributionRate }}%</text></view
  129. >
  130. </view>
  131. </view>
  132. </view>
  133. </CommonSection>
  134. <!-- 审批记录 -->
  135. <CommonSection title="审批记录" v-if="form.id">
  136. <FlowTable
  137. :id="form.id"
  138. :businessCode="'学术著作-' + String(form.workCode)"
  139. defCode="sci_academic_achievement"
  140. />
  141. </CommonSection>
  142. </template>
  143. <uv-empty v-else mode="data" text="暂无数据"></uv-empty>
  144. </view>
  145. </template>
  146. <script setup lang="ts">
  147. import { ref, onMounted, watch, computed } from "vue";
  148. import { useDict } from "@/hooks/useDict";
  149. import { useDocumentApi } from "@/api/document";
  150. import { formatDate } from "@/utils/date";
  151. import { previewFile } from "@/utils/file";
  152. import to from "await-to-js";
  153. import FlowTable from "@/pages/project/components/detail/FlowTable.vue";
  154. import CommonSection from "@/components/ui/CommonSection.vue";
  155. import CommonInfoRow from "@/components/ui/CommonInfoRow.vue";
  156. const props = defineProps<{
  157. code: string;
  158. }>();
  159. const { getDictLabel } = useDict(
  160. "sci_work_class",
  161. "sci_work_publisherType",
  162. "sci_work_roleContent"
  163. );
  164. const documentApi = useDocumentApi();
  165. const form = ref<any>(null);
  166. const loading = ref(false);
  167. const platformList = computed(() => {
  168. if (form.value?.belongPlatform) {
  169. try {
  170. const data = JSON.parse(form.value.belongPlatform);
  171. return Array.isArray(data) ? data : [];
  172. } catch (e) {
  173. if (form.value.belongPlatform === "其他")
  174. return [{ platformName: "其他" }];
  175. return [{ platformName: form.value.belongPlatform }];
  176. }
  177. }
  178. return [];
  179. });
  180. const workFileList = computed(() => {
  181. if (!form.value?.workFile) return [];
  182. try {
  183. const files = JSON.parse(form.value.workFile);
  184. return Array.isArray(files) ? files : [files];
  185. } catch (e) {
  186. return [];
  187. }
  188. });
  189. const handlePreview = (file: any) => {
  190. const url = file.fileUrl || file.url;
  191. const name = file.fileName || file.name;
  192. if (url) {
  193. previewFile(url, name);
  194. }
  195. };
  196. const fetchData = async () => {
  197. if (!props.code) return;
  198. loading.value = true;
  199. const workCode = props.code.includes("-")
  200. ? props.code.split("-")[1]
  201. : props.code;
  202. const [err, res] = await to(documentApi.getWorkByCode(workCode));
  203. if (!err && res?.data) {
  204. form.value = res.data;
  205. }
  206. loading.value = false;
  207. };
  208. onMounted(() => {
  209. fetchData();
  210. });
  211. watch(
  212. () => props.code,
  213. () => {
  214. fetchData();
  215. }
  216. );
  217. </script>
  218. <style lang="scss" scoped>
  219. @import "./common.scss";
  220. .platform-tags {
  221. display: flex;
  222. flex-wrap: wrap;
  223. justify-content: flex-end;
  224. gap: 8rpx;
  225. flex: 1;
  226. align-items: center;
  227. }
  228. .file-links {
  229. .file-item {
  230. padding: 6rpx 0;
  231. }
  232. .file-link {
  233. color: #2979ff;
  234. text-decoration: underline;
  235. word-break: break-all;
  236. }
  237. }
  238. </style>