Browse Source

📦 对接自查表打包下载

快乐的梦鱼 2 weeks ago
parent
commit
63c557e646

+ 32 - 0
src/api/collect/AssessmentContent.ts

@@ -935,6 +935,38 @@ export class AssessmentContentApi extends AppServerRequestModule<DataModel> {
     const res = await this.post<KeyValue>('/ich/check/agreementDetail', '传承协议详情', { id, user_id: userId });
     return transformDataModel<AgreementDetail>(AgreementDetail, res.requireData());
   }
+
+  /**
+   * 打包传承人自查表、汇总表zip下载
+   * @see https://www.showdoc.com.cn/minnanCE/11559060626887137
+   */
+  async downloadCheckZip(data: { year?: number; progress?: number }) {
+    const auth = useAuthStore();
+    let url = `${this.config.baseUrl}/inheritor_check_download/index`;
+    url = appendGetUrlParams(url, 'main_body_id', ApiCofig.mainBodyId);
+    url = appendGetUrlParams(url, 'token', auth.token);
+    if (data.year) url = appendGetUrlParams(url, 'year', String(data.year));
+    if (data.progress !== undefined) url = appendGetUrlParams(url, 'progress', String(data.progress));
+    const res = await fetch(url, {
+      method: 'POST',
+      headers: {
+        token: auth.token,
+        __token__: auth.token,
+      },
+    });
+    if (!res.ok)
+      throw new Error('下载失败,状态码:' + res.status);
+    const blob = await res.blob();
+    const objectUrl = URL.createObjectURL(blob);
+    const a = document.createElement('a');
+    a.href = objectUrl;
+    a.download = `自查表汇总-${data.year || '全部'}.zip`;
+    a.rel = 'noopener';
+    document.body.appendChild(a);
+    a.click();
+    document.body.removeChild(a);
+    URL.revokeObjectURL(objectUrl);
+  }
 }
 
 export default new AssessmentContentApi();

+ 32 - 28
src/components/content/CommonListBlock.vue

@@ -21,36 +21,40 @@
           <div v-if="showTotal" class="nav-back-title">
             共有 {{ newsLoader.total }} 个{{ title }}
           </div>
-          <slot name="headLeft"></slot>
         </div>
         <!-- 右栏 -->
-        <div class="col-sm-12 col-md-6 col-lg-6 flex flex-row justify-end items-start flex-wrap gap-1.25">
-          <Dropdown
-            v-for="(drop, k) in dropDownNames" :key="k" 
-            :selectedValue="dropDownValues[k]"
-            :options="drop.options" 
-            labelKey="name"
-            valueKey="id"
-            @update:selectedValue="(v) => handleChangeDropDownValue(k, v)"
-          />
-          <SimpleInput 
-            v-if="showSearch" v-model="searchText" 
-            class="max-w-40 md:max-w-50 lg:max-w-75"
-            placeholder="请输入关键词" 
-            @search="handleSearch"
-          >
-            <template #suffix>
-              <IconSearch
-                class="search-icon"
-                src="@/assets/images/news/IconSearch.png"
-                alt="搜索" 
-                @click="newsLoader.load(true)"
-              />
-            </template>
-          </SimpleInput>
-          <button class="tab-button" v-if="showTableSwitch" @click="tableListShow=!tableListShow">
-            ▼ 清单
-          </button>
+        <div class="col-sm-12 col-md-6 col-lg-6 flex flex-row justify-between items-start flex-wrap gap-1.25">
+          <div class="flex flex-row align-center gap-1.25">
+            <slot name="headLeft"></slot>
+          </div>
+          <div class="flex flex-row align-center gap-1.25">
+            <Dropdown
+              v-for="(drop, k) in dropDownNames" :key="k" 
+              :selectedValue="dropDownValues[k]"
+              :options="drop.options" 
+              labelKey="name"
+              valueKey="id"
+              @update:selectedValue="(v) => handleChangeDropDownValue(k, v)"
+            />
+            <SimpleInput 
+              v-if="showSearch" v-model="searchText" 
+              class="max-w-40 md:max-w-50 lg:max-w-75"
+              placeholder="请输入关键词" 
+              @search="handleSearch"
+            >
+              <template #suffix>
+                <IconSearch
+                  class="search-icon"
+                  src="@/assets/images/news/IconSearch.png"
+                  alt="搜索" 
+                  @click="newsLoader.load(true)"
+                />
+              </template>
+            </SimpleInput>
+            <button class="tab-button" v-if="showTableSwitch" @click="tableListShow=!tableListShow">
+              ▼ 清单
+            </button>
+          </div>
         </div>
       </div>
     </div>

+ 12 - 3
src/components/controls/Dropdown.vue

@@ -85,7 +85,7 @@ function selectOption(option: any) {
   flex-direction: row;
   align-items: center;
   justify-content: space-between;
-  padding: 6px 8px;
+  padding: 10px 14px;
   background-color: $box-inset-color;
   border: 1px solid $primary-color;
   user-select: none;
@@ -94,7 +94,12 @@ function selectOption(option: any) {
   overflow: hidden;
   text-overflow: ellipsis;
   max-width: 100%;
-  font-size: 12px;
+  font-size: 16px;
+
+  @media (max-width: 768px) {
+    padding: 6px 8px;
+    font-size: 12px;
+  }
 
   .arrow {
     width: 15px;
@@ -107,12 +112,16 @@ function selectOption(option: any) {
     }
   }
   span {
-    font-size: 12px;
+    font-size: inherit;
     color: var(--nana-text-1);
     max-width: calc(100% - 25px);
     white-space: nowrap;
     overflow: hidden;
     text-overflow: ellipsis;
+
+    @media (max-width: 768px) {
+      font-size: 12px;
+    }
   }
 }
 .nana-dropdown-options {

+ 12 - 3
src/components/controls/SimpleInput.vue

@@ -60,11 +60,16 @@ function handleBlur() {
   flex-direction: row;
   align-items: center;
   justify-content: space-between;
-  padding: 3px 6px;
+  padding: 10px 14px;
   background-color: $box-color;
-  font-size: 12px;
+  font-size: 16px;
   border: 1px solid $border-default-color;
 
+  @media (max-width: 768px) {
+    padding: 3px 6px;
+    font-size: 12px;
+  }
+
   &.focus {
     border-color: $border-active-color; 
   }
@@ -108,6 +113,10 @@ function handleBlur() {
 }
 .nana-input-text {
   color: $text-color;
-  font-size: 12px;
+  font-size: 20px;
+
+  @media (max-width: 768px) {
+    font-size: 12px;
+  }
 }
 </style>

+ 61 - 0
src/pages/collect/assessment/evaluation-form-list.vue

@@ -21,6 +21,9 @@
         :load="(page: number, pageSize: number, _tag: number, searchText: string, drop: number[]) => loadSelfAssessmentAdminList(page, pageSize, searchText, drop)"
         :show-detail="handleReviewSelfAssessment"
       >
+        <template #headLeft>
+          <a-button type="primary" @click="openDownloadModal">打包下载</a-button>
+        </template>
         <template #itemRight="{ item }">
           <a-popover v-if="item.rejectType && item.rejectType > 0" title="退回原因" trigger="hover">
             <template #content>
@@ -73,6 +76,26 @@
       </CommonListBlock>
     </a-tab-pane>
   </a-tabs>
+
+  <a-modal
+    v-model:open="showDownloadModal"
+    title="打包下载自查表"
+    @ok="handleDownloadZip"
+    :confirmLoading="downloading"
+    okText="下载"
+    cancelText="取消"
+  >
+    <a-form layout="vertical">
+      <a-form-item label="年份">
+        <a-input-number v-model:value="downloadYear" :min="2020" :max="2030" style="width: 100%" />
+      </a-form-item>
+      <a-form-item label="状态">
+        <a-select v-model:value="downloadProgress" style="width: 100%">
+          <a-select-option v-for="opt in downloadProgressOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</a-select-option>
+        </a-select>
+      </a-form-item>
+    </a-form>
+  </a-modal>
 </template>
 
 <script setup lang="ts">
@@ -90,6 +113,11 @@ const router = useRouter();
 
 const activeKey = ref('1');
 
+const showDownloadModal = ref(false);
+const downloading = ref(false);
+const downloadYear = ref(new Date().getFullYear() - 1);
+const downloadProgress = ref(-100);
+
 const { variable: lastSelfAssessmentProgress } = useMemorizeVar('adminSelfAssessmentProgress', -100);
 const { variable: lastSelfAssessmentLevel } = useMemorizeVar('adminSelfAssessmentLevel', 0);
 const { variable: lastCheckLogStatus } = useMemorizeVar('adminCheckLogStatus', 0);
@@ -128,6 +156,17 @@ const checkLogReviewTypeOptions: DropdownCommonItem[] = [
   { id: 5, name: '省文化和旅游厅' },
 ];
 
+const downloadProgressOptions: DropdownCommonItem[] = [
+  { id: -100, name: '全部状态' },
+  { id: -1, name: '未提交' },
+  { id: 0, name: '草稿' },
+  { id: 1, name: '已提交审核' },
+  { id: 2, name: '项目保护单位审核完成' },
+  { id: 3, name: '县(区)文旅部门审核完成' },
+  { id: 4, name: '设区市文旅部门/省非遗中心审核完成' },
+  { id: 5, name: '省文化和旅游厅审核完成' },
+];
+
 
 const authStore = useAuthStore();
 const currentUserGroups = computed(() => authStore.userInfo?.adminGroup || []);
@@ -223,4 +262,26 @@ function handleReviewSelfAssessment(item: SelfAssessmentDetail) {
     },
   });
 }
+
+async function handleDownloadZip() {
+  downloading.value = true;
+  try {
+    const progress = downloadProgress.value > -50 ? downloadProgress.value : undefined;
+    await AssessmentContentApi.downloadCheckZip({
+      year: downloadYear.value,
+      progress,
+    });
+    showDownloadModal.value = false;
+    message.success('下载成功');
+  } catch (e: any) {
+    message.error(e?.message || '下载失败');
+  } finally {
+    downloading.value = false;
+  }
+}
+
+function openDownloadModal() {
+  downloadProgress.value = lastSelfAssessmentProgress.value;
+  showDownloadModal.value = true;
+}
 </script>

+ 2 - 2
src/pages/test.vue

@@ -1,9 +1,9 @@
 <template>
   <div class="flex flex-col gap-2">
-    <p class="break-all">directAuthInfo: {{ directAuthInfo }} 
+    <div class="break-all">directAuthInfo: {{ directAuthInfo }} 
       <pre>decodeURIComponent: {{ decodeURIComponent(directAuthInfo) }}</pre>
       <pre>{{ prasedDirectAuthInfo }}</pre>
-    </p>
+    </div>
     <p v-if="err" class="text-red-600">err: {{ err }}</p>
     <p>isInMiniProgram: {{ isInMiniProgram }}</p>
   </div>