AchPaperForm.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <template>
  2. <view class="document-form">
  3. <uv-loading-icon v-if="loading" mode="circle" text="正在加载学术论文详情..."></uv-loading-icon>
  4. <template v-else-if="form">
  5. <!-- 基本信息 -->
  6. <CommonSection title="基本信息" :isFirst="true">
  7. <CommonInfoRow label="题目" :value="form.paperName" />
  8. <CommonInfoRow label="学科类型" :value="getDictLabel('project_class', form.disciplineFirstName)" />
  9. <CommonInfoRow label="论文类型" :value="form.paperType" />
  10. <CommonInfoRow label="论文类别" :value="getDictLabel('paper_category', form.paperCategory)" />
  11. <CommonInfoRow label="发表/出版时间" :value="formatDate(form.publicationDate)" />
  12. <CommonInfoRow label="刊名" :value="form.publicationName" />
  13. <CommonInfoRow label="期刊类型" :value="form.periodicalType || '-'" />
  14. <CommonInfoRow v-if="isConferenceType" label="会议名称" :value="form.conferenceName || '-'" />
  15. <CommonInfoRow v-if="isConferenceType" label="会议地址" :value="form.conferenceAddress || '-'" />
  16. <template v-if="form.periodicalType?.toLowerCase() === 'sci'">
  17. <CommonInfoRow label="中科院分区" :value="getDictLabel('sci_paper_subTreasury', form.subTreasury)" />
  18. <CommonInfoRow label="IF" :value="form.impactFactors" />
  19. </template>
  20. <CommonInfoRow label="论文DOI号/PMID((PubMed标识码)" :isColumn="true" :value="form.doi" />
  21. <CommonInfoRow label="所属年份" :value="form.statisticalYear ? formatDate(form.statisticalYear, 'YYYY') : '-'" />
  22. <CommonInfoRow label="年、卷(期)" :value="`${form.yearNum || ''}、${form.volNum || ''}(${form.issueNum || ''})`" />
  23. <CommonInfoRow v-if="form.pageRange" label="页码" :value="form.pageRange" />
  24. <CommonInfoRow label="本院署名" :value="getDictLabel('sci_paper_signType', form.signType)" />
  25. <CommonInfoRow label="ISSN号" :value="form.issnNum" />
  26. <CommonInfoRow label="合作单位" :value="form.partnerOrg || '-'" />
  27. <CommonInfoRow label="单位类型" :value="getDictLabel('partner_org_type', form.partnerOrgType)" />
  28. <CommonInfoRow label="所属平台" isColumn>
  29. <view class="platform-tags">
  30. <template v-if="platformList.length > 0">
  31. <uv-tags v-for="(p, index) in platformList" :key="index" :text="p.platformName === '其他' ? '其他' : (p.platformType ? p.platformName + ' (' + p.platformType + ')' : p.platformName)" type="primary" plain size="mini" class="mr5"></uv-tags>
  32. </template>
  33. <text v-else>-</text>
  34. </view>
  35. </CommonInfoRow>
  36. <CommonInfoRow label="所属团队" :value="form.belongTeam || '-'" />
  37. </CommonSection>
  38. <!-- 作者信息 -->
  39. <CommonSection title="作者信息" v-if="form.authorList?.length">
  40. <view class="member-list">
  41. <view class="member-item" v-for="(row, index) in form.authorList" :key="index">
  42. <view class="m-index">{{ Number(index) + 1 }}</view>
  43. <view class="m-body">
  44. <view class="member-header">
  45. <view class="name-box">
  46. <text class="m-name">{{ row.memberName }}</text>
  47. <text class="m-tag">{{ getDictLabel('sci_paper_author_type', row.authorType) }}</text>
  48. </view>
  49. <text class="m-type-tag">{{ getDictLabel('sci_paper_member_type', row.memberType) }}</text>
  50. </view>
  51. <view class="m-detail-row">
  52. <view class="m-line" v-if="row.deptName"><text class="l">科室/单位:</text><text class="v">{{ row.deptName }}</text></view>
  53. <view class="m-line" v-if="row.technicalTitle"><text class="l">职称:</text><text class="v">{{ row.technicalTitle }}</text></view>
  54. <view class="m-line" v-if="row.contributionRate"><text class="l">贡献率(%):</text><text class="v">{{ row.contributionRate }}</text></view>
  55. <view class="m-line" v-if="row.signOrder"><text class="l">排名:</text><text class="v">{{ row.signOrder }}</text></view>
  56. </view>
  57. </view>
  58. </view>
  59. </view>
  60. </CommonSection>
  61. <!-- 关联项目 -->
  62. <CommonSection title="关联项目" v-if="form.projList?.length">
  63. <view class="achievement-card" v-for="(item, index) in form.projList" :key="index">
  64. <view class="a-row">
  65. <text class="al">关联类型:</text>
  66. <text class="av">{{ item.sourceType === '10' ? '项目' : '学科' }}</text>
  67. </view>
  68. <view class="a-row">
  69. <text class="al">项目/学科:</text>
  70. <text class="av">{{ item.projectSource || '-' }}</text>
  71. </view>
  72. </view>
  73. </CommonSection>
  74. <!-- 电子附件 -->
  75. <CommonSection title="电子附件">
  76. <CommonInfoRow label="论文全文" isColumn>
  77. <view class="file-hint">附件说明:SCI上传文章;中文期刊上传封面、目录及文章</view>
  78. <view class="file-links">
  79. <template v-if="paperResultList.length">
  80. <view class="file-item" v-for="(item, index) in paperResultList" :key="'paper-full-' + index" @click="handlePreview(item)">
  81. <text class="file-link">{{ item.fileName || item.name || '-' }}</text>
  82. </view>
  83. </template>
  84. <text v-else>-</text>
  85. </view>
  86. </CommonInfoRow>
  87. <CommonInfoRow label="收录证明" isColumn>
  88. <view class="file-links">
  89. <template v-if="includedProofList.length">
  90. <view class="file-item" v-for="(item, index) in includedProofList" :key="'paper-included-' + index" @click="handlePreview(item)">
  91. <text class="file-link">{{ item.fileName || item.name || '-' }}</text>
  92. </view>
  93. </template>
  94. <text v-else>-</text>
  95. </view>
  96. </CommonInfoRow>
  97. <CommonInfoRow label="伦理批件" isColumn>
  98. <view class="file-links">
  99. <template v-if="ethicsApprovalList.length">
  100. <view class="file-item" v-for="(item, index) in ethicsApprovalList" :key="'paper-ethics-' + index" @click="handlePreview(item)">
  101. <text class="file-link">{{ item.fileName || item.name || '-' }}</text>
  102. </view>
  103. </template>
  104. <text v-else>-</text>
  105. </view>
  106. </CommonInfoRow>
  107. <CommonInfoRow label="原始数据" isColumn>
  108. <view class="file-links">
  109. <template v-if="rawDataList.length">
  110. <view class="file-item" v-for="(item, index) in rawDataList" :key="'paper-raw-' + index" @click="handlePreview(item)">
  111. <text class="file-link">{{ item.fileName || item.name || '-' }}</text>
  112. </view>
  113. </template>
  114. <text v-else>-</text>
  115. </view>
  116. </CommonInfoRow>
  117. </CommonSection>
  118. <!-- 审批信息 -->
  119. <CommonSection title="审批信息" v-if="form.id">
  120. <FlowTable :id="form.id" :businessCode="'学术论文-' + form.paperCode" defCode="sci_academic_achievement" />
  121. </CommonSection>
  122. </template>
  123. <uv-empty v-else mode="data" text="暂无数据"></uv-empty>
  124. </view>
  125. </template>
  126. <script setup lang="ts">
  127. import { ref, onMounted, watch, computed } from 'vue';
  128. import { useDict } from '@/hooks/useDict';
  129. import { useDocumentApi } from '@/api/document';
  130. import { formatDate } from '@/utils/date';
  131. import { previewFile } from '@/utils/file';
  132. import to from 'await-to-js';
  133. import FlowTable from '@/pages/project/components/detail/FlowTable.vue';
  134. import CommonSection from '@/components/ui/CommonSection.vue';
  135. import CommonInfoRow from '@/components/ui/CommonInfoRow.vue';
  136. const props = defineProps<{
  137. code: string;
  138. }>();
  139. const { getDictLabel } = useDict(
  140. 'project_class',
  141. 'sci_paper_type',
  142. 'paper_category',
  143. 'sci_publication_range',
  144. 'sci_paper_subTreasury',
  145. 'sci_paper_signType',
  146. 'sci_paper_author_type',
  147. 'sci_paper_member_type',
  148. 'partner_org_type'
  149. );
  150. const documentApi = useDocumentApi();
  151. const form = ref<any>(null);
  152. const loading = ref(false);
  153. const platformList = computed(() => {
  154. if (form.value?.belongPlatform) {
  155. try {
  156. const data = JSON.parse(form.value.belongPlatform);
  157. return Array.isArray(data) ? data : [];
  158. } catch (e) {
  159. if (form.value.belongPlatform === '其他') return [{ platformName: '其他' }];
  160. return [{ platformName: form.value.belongPlatform }];
  161. }
  162. }
  163. return [];
  164. });
  165. const paperResultList = computed(() => form.value?.paperResultList || []);
  166. const includedProofList = computed(() => form.value?.includedProofList || []);
  167. const ethicsApprovalList = computed(() => form.value?.ethicsApprovalList || []);
  168. const rawDataList = computed(() => form.value?.rawDataList || []);
  169. const isConferenceType = computed(() => {
  170. const paperType = String(form.value?.paperType || '');
  171. return paperType.includes('会议');
  172. });
  173. const handlePreview = (file: any) => {
  174. const url = file.fileUrl || file.url;
  175. const name = file.fileName || file.name;
  176. if (url) {
  177. previewFile(url, name);
  178. }
  179. };
  180. const fetchData = async () => {
  181. if (!props.code) return;
  182. loading.value = true;
  183. const paperCode = props.code.includes('-') ? props.code.split('-')[1] : props.code;
  184. const [err, res] = await to(documentApi.getPaperByCode(paperCode));
  185. if (!err && res?.data) {
  186. form.value = res.data;
  187. }
  188. loading.value = false;
  189. };
  190. onMounted(() => {
  191. fetchData();
  192. });
  193. watch(() => props.code, () => {
  194. fetchData();
  195. });
  196. </script>
  197. <style lang="scss" scoped>
  198. @import "./common.scss";
  199. .info-row {
  200. display: flex;
  201. justify-content: space-between;
  202. padding: 24rpx 0;
  203. border-bottom: 2rpx dashed #f5f5f5;
  204. font-size: 28rpx;
  205. .label {
  206. color: #343a3f;
  207. width: 200rpx;
  208. flex-shrink: 0;
  209. margin-right: 20rpx;
  210. }
  211. }
  212. .member-list {
  213. .member-item {
  214. display: flex;
  215. align-items: flex-start;
  216. padding: 20rpx 0;
  217. border-bottom: 2rpx solid #f5f5f5;
  218. &:last-child { border-bottom: none; }
  219. }
  220. .m-index {
  221. width: 40rpx;
  222. height: 40rpx;
  223. background: #3b82f6;
  224. color: #fff;
  225. border-radius: 50%;
  226. display: flex;
  227. align-items: center;
  228. justify-content: center;
  229. font-size: 22rpx;
  230. flex-shrink: 0;
  231. margin-right: 16rpx;
  232. margin-top: 4rpx;
  233. }
  234. .m-body {
  235. flex: 1;
  236. }
  237. }
  238. .member-header {
  239. .name-box {
  240. display: flex;
  241. align-items: center;
  242. gap: 12rpx;
  243. flex-wrap: wrap;
  244. }
  245. }
  246. .m-detail-row {
  247. margin-top: 12rpx;
  248. display: flex;
  249. flex-direction: column;
  250. gap: 6rpx;
  251. .m-line {
  252. font-size: 24rpx;
  253. color: #64748b;
  254. .l { color: #94a3b8; margin-right: 8rpx; }
  255. .v { color: #343a3f; }
  256. }
  257. }
  258. .file-hint {
  259. font-size: 22rpx;
  260. color: #ef4444;
  261. margin-bottom: 8rpx;
  262. }
  263. .file-links {
  264. .file-item {
  265. padding: 6rpx 0;
  266. }
  267. .file-link {
  268. color: #2979ff;
  269. text-decoration: underline;
  270. word-break: break-all;
  271. }
  272. }
  273. </style>