detail.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <template>
  2. <view class="detail-container">
  3. <view class="header-card">
  4. <view class="title">{{ form.projectName || '未知名称' }}</view>
  5. <view class="meta-row">
  6. <view class="leader" v-if="form.projectIncharge">
  7. 项目负责人:{{ form.projectIncharge }}
  8. </view>
  9. <view class="tags">
  10. <text class="tag bg-blue">{{ getProjectTypeLabel(form.projectType) }}</text>
  11. </view>
  12. </view>
  13. </view>
  14. <view class="scroll-wrapper">
  15. <scroll-view scroll-y class="content-area" :show-scrollbar="false">
  16. <view class="component-wrapper">
  17. <CommonSection title="项目信息">
  18. <CommonInfoRow label="预算金额" :value="amountUnitFormatter(form.contractAmount) + '元'" :isAmount="true" />
  19. </CommonSection>
  20. <CommonSection title="入账经费">
  21. <CommonInfoRow label="经费类型" :value="formatAmountType(form.amountType)" />
  22. <CommonInfoRow label="入账金额" :value="amountUnitFormatter(form.amount) + '元'" :isAmount="true" />
  23. <CommonInfoRow label="入账时间" :value="formatDate(form.applyTime, 'YYYY-MM-DD')" />
  24. <CommonInfoRow label="拨款单位" :value="form.allotUnit" />
  25. <CommonInfoRow label="拨款时间" :value="formatDate(form.allotTime, 'YYYY-MM-DD')" />
  26. <CommonInfoRow label="入账说明" :value="form.remark" />
  27. </CommonSection>
  28. <CommonSection title="预算情况" v-if="form.fundsList && form.fundsList.length > 0">
  29. <CommonInfoRow v-for="(item, index) in form.fundsList" :key="item.id || index" :label="item.subjName"
  30. :value="amountUnitFormatter(item.amount) + '元'" :isAmount="true" />
  31. </CommonSection>
  32. </view>
  33. </scroll-view>
  34. </view>
  35. </view>
  36. </template>
  37. <script lang="ts" setup>
  38. import { ref } from 'vue';
  39. import { onLoad } from '@dcloudio/uni-app';
  40. import { useClaimApi } from '@/api/fund/index';
  41. import { formatDate } from '@/utils/date';
  42. import CommonSection from '@/components/ui/CommonSection.vue';
  43. import CommonInfoRow from '@/components/ui/CommonInfoRow.vue';
  44. const claimApi = useClaimApi();
  45. const form = ref<any>({
  46. id: 0,
  47. amount: '', //金额(元)
  48. projectName: '',
  49. projectType: '',
  50. contractAmount: '',
  51. projectIncharge: '',
  52. applyTime: '',
  53. amountType: '',
  54. allotUnit: '',
  55. allotTime: '',
  56. remark: '',
  57. fundsList: []
  58. });
  59. const getProjectTypeLabel = (type: string) => {
  60. const map: Record<string, string> = {
  61. '10': '纵向项目',
  62. '20': '横向项目',
  63. '30': '内部项目',
  64. '40': '重点学科',
  65. '50': '人才类项目',
  66. '60': '科研平台'
  67. };
  68. return map[type] || '-';
  69. };
  70. const formatAmountType = (type: string) => {
  71. const amountTypeOptions = [
  72. { value: '10', label: '财政拨款' },
  73. { value: '20', label: '匹配经费' },
  74. { value: '30', label: '自筹经费' }
  75. ];
  76. const find = amountTypeOptions.find((item) => item.value == type);
  77. return find ? find.label : '-';
  78. };
  79. const amountUnitFormatter = (val: any) => {
  80. if (val === null || val === undefined || val === '') return '0.00';
  81. const num = Number(val);
  82. return isNaN(num) ? '0.00' : num.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  83. };
  84. const getFundDetail = async (id: number) => {
  85. try {
  86. const res: any = await claimApi.getRecordDetails({ id });
  87. if (res.code == 200 && res.data) {
  88. form.value = { ...form.value, ...res.data };
  89. }
  90. } catch (err) {
  91. console.error('获取详情失败', err);
  92. }
  93. };
  94. onLoad((options: any) => {
  95. const id = options.id ? Number(options.id) : 0;
  96. if (id) {
  97. getFundDetail(id);
  98. }
  99. });
  100. </script>
  101. <style lang="scss" scoped>
  102. .detail-container {
  103. height: calc(100vh - var(--window-top));
  104. display: flex;
  105. flex-direction: column;
  106. background-color: #f5f7fa;
  107. box-sizing: border-box;
  108. }
  109. .header-card {
  110. flex-shrink: 0;
  111. background: linear-gradient(135deg, #1c9bfd 0%, #15a982 100%);
  112. padding: 40rpx 30rpx 40rpx;
  113. color: #fff;
  114. border-bottom-left-radius: 40rpx;
  115. border-bottom-right-radius: 40rpx;
  116. box-shadow: 0 10rpx 20rpx rgba(28, 155, 253, 0.2);
  117. .title {
  118. font-size: 40rpx;
  119. font-weight: bold;
  120. margin-bottom: 20rpx;
  121. line-height: 1.4;
  122. }
  123. .meta-row {
  124. display: flex;
  125. align-items: center;
  126. justify-content: space-between;
  127. gap: 20rpx;
  128. }
  129. .leader {
  130. font-size: 28rpx;
  131. opacity: 0.9;
  132. }
  133. .tags {
  134. display: flex;
  135. flex-wrap: wrap;
  136. gap: 16rpx;
  137. .tag {
  138. font-size: 24rpx;
  139. padding: 6rpx 20rpx;
  140. border-radius: 30rpx;
  141. border: 2rpx solid rgba(255, 255, 255, 0.4);
  142. background: rgba(255, 255, 255, 0.1);
  143. backdrop-filter: blur(4px);
  144. }
  145. }
  146. }
  147. .scroll-wrapper {
  148. flex: 1;
  149. overflow: hidden;
  150. margin-top: 10rpx;
  151. }
  152. .content-area {
  153. height: 100%;
  154. }
  155. .component-wrapper {
  156. margin: 0 30rpx;
  157. padding-top: 20rpx;
  158. padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
  159. }
  160. </style>