Browse Source

feature 1001567

参考文献段落标记为使用功能实现
Kevin Jiang 2 years ago
parent
commit
8cf33e9ebb

+ 20 - 0
src/client/paperSection.client.ts

@@ -0,0 +1,20 @@
+import httpClient from "@/services/httpClient";
+import * as urlHelper from "@/libs/url.lib"
+import type { Response } from "@/types/response.types"
+
+const _url = urlHelper.withPrefix("/gw/user/paperSection")
+
+export async function record(sectionId: number): Promise<boolean> {
+  const resp = await httpClient.post<Response<boolean>>(_url(sectionId))
+  return resp.data.data;
+}
+
+export async function cancel(sectionId: number): Promise<boolean> {
+  const resp = await httpClient.delete<Response<boolean>>(_url(sectionId))
+  return resp.data.data
+}
+
+export async function query(sectionIds: number[]): Promise<Record<number, boolean>> {
+  const resp = await httpClient.post<Response<Record<number, boolean>>>(_url("/query"), sectionIds)
+  return resp.data.data
+}

+ 1 - 1
src/services/httpClient.ts

@@ -40,7 +40,7 @@ httpClient.interceptors.response.use(function (response) {
             errorMsgHandler()
         }
         errorMsgHandler = message.error(error.message);
-        routeToLogin();
+        // routeToLogin();
     }
 
     return Promise.reject(error);

+ 13 - 0
src/services/paperSection.service.ts

@@ -0,0 +1,13 @@
+import * as paperSectionClient from "@/client/paperSection.client"
+
+export async function record(sectionId: number) {
+  return paperSectionClient.record(sectionId)
+}
+
+export async function cancel(sectionId: number) {
+  return paperSectionClient.cancel(sectionId)
+}
+
+export async function query(sectionIds: number[]): Promise<Record<number, boolean>> {
+  return paperSectionClient.query(sectionIds)
+}

+ 1 - 1
src/types/search.types.ts

@@ -49,7 +49,7 @@ export interface UnitScholar {
 }
 
 export interface ChapterSearchDocResponse {
-  id: string;
+  id: number;
   score: number;
   filename: string;
   section: string;

+ 13 - 2
src/views/report/components/ChapterEditor.vue

@@ -41,6 +41,7 @@ const emits = defineEmits<{
   (e: "moveUp"): void;
   (e: "moveDown"): void;
   (e: "remove"): void;
+  (e: "sectionRecordUse", sectionId: number): void;
 }>();
 
 watch(
@@ -109,6 +110,10 @@ function onInsert(text: string) {
 function onReferenceDrawClose() {
   contentEditor.value?.focus()
 }
+
+function onSectionRecordUse(sectionId: number) {
+  emits("sectionRecordUse", sectionId)
+}
 </script>
 
 <template>
@@ -175,11 +180,17 @@ function onReferenceDrawClose() {
     <div class="chapter-button-group" v-if="contentEditorVisible">
       <a-space>
         <a-button @click="searchReference">查找参考文献</a-button>
-        <a-button>自动生成</a-button>
+        <a-button disabled>自动生成(二期)</a-button>
       </a-space>
     </div>
   </div>
-  <ReferenceDraw :keywords="data.keywords || []" ref="referenceDraw" @insert="onInsert" @close="onReferenceDrawClose" />
+  <ReferenceDraw
+    :keywords="data.keywords || []"
+    ref="referenceDraw"
+    @insert="onInsert"
+    @close="onReferenceDrawClose"
+    @recordUse="onSectionRecordUse"
+  />
 </template>
 
 <style scoped lang="scss">

+ 31 - 2
src/views/report/components/reference/ReferenceDraw.vue

@@ -6,6 +6,7 @@ import ReferenceSearchBox from "./ReferenceSearchBox.vue";
 import ReferenceSearchResultItem from "./ReferenceSearchResultItem.vue";
 import type { ChapterSearchDocResponse, ChapterSearchRequest } from "@/types/search.types"
 import * as chapterSearchService from "@/services/chapterSearch.service"
+import * as paperSectionService from "@/services/paperSection.service"
 import { CompLog } from "@/libs/log.lib";
 import SpinComponent from "@/components/SpinComponent.vue";
 
@@ -19,6 +20,7 @@ const props = defineProps({
 const emits = defineEmits<{
   (e: "insert", text: string): void;
   (e: "close"): void;
+  (e: "recordUse", sectionId: number): void;
 }>();
 
 // 组件可见状态
@@ -27,6 +29,8 @@ const visible = ref<boolean>(false);
 const total = ref(0)
 // 章节搜索结果
 const referenceSearchResult: Ref<ChapterSearchDocResponse[]> = ref([]);
+// 文献章节段落内容是否使用ref
+const paperSectionUsage = ref<Record<number, boolean>>({})
 // 章节搜索状态
 const loading = ref(false)
 // 翻页
@@ -57,6 +61,12 @@ function getSearchRequest(): ChapterSearchRequest {
   return request
 }
 
+function querySectionUsage(sectionIds: number[]) {
+  paperSectionService.query(sectionIds).then((usages) => {
+    paperSectionUsage.value = usages
+  })
+}
+
 function search(request: ChapterSearchRequest) {
   loading.value = true
   referenceSearchResult.value = []
@@ -64,6 +74,8 @@ function search(request: ChapterSearchRequest) {
     loading.value = false
     total.value = resp.total
     referenceSearchResult.value = resp.items
+
+    querySectionUsage(resp.items.map(item => item.id))
   }).catch((err) => {
     CompLog.logErr("ReferenceDraw")(err)
     loading.value = false
@@ -88,6 +100,18 @@ function onReferenceSearchWithInSearch(queryWithInKeywordsIn: string[]) {
   search(getSearchRequest())
 }
 
+function onSectionRecordUse(sectionId: number) {
+  paperSectionService.record(sectionId).then(() => {
+    paperSectionUsage.value[`${sectionId}`] = true
+  })
+}
+
+function onSectionRecordCancel(sectionId: number) {
+  paperSectionService.cancel(sectionId).then(() => {
+    paperSectionUsage.value[`${sectionId}`] = false
+  })
+}
+
 const onClose = () => {
   visible.value = false;
   emits("close")
@@ -112,7 +136,6 @@ defineExpose({
     title="检索参考文献"
     placement="right"
     :visible="visible"
-    :destroyOnClose="true"
     @close="onClose"
     class="reference-drawer"
   >
@@ -125,7 +148,13 @@ defineExpose({
     </a-divider>
     <SpinComponent :spinning="loading">
       <div v-for="(item, index) in referenceSearchResult" :key="index">
-        <ReferenceSearchResultItem :data="item" @insert="emits('insert', $event)" />
+        <ReferenceSearchResultItem
+          :data="item"
+          :used="paperSectionUsage[item.id] || false"
+          @insert="emits('insert', $event)"
+          @record-use="onSectionRecordUse"
+          @record-cancel="onSectionRecordCancel"
+        />
         <a-divider class="result-item-divider" v-if="index < referenceSearchResult.length - 1" />
       </div>
       <div class="pigination-wrap">

+ 23 - 2
src/views/report/components/reference/ReferenceSearchResultItem.vue

@@ -2,17 +2,24 @@
 import { useClipboard } from "@/libs/clipboard.lib";
 import type { ChapterSearchDocResponse } from "@/types/search.types";
 import { message } from "ant-design-vue";
+import { ExclamationCircleFilled } from "@ant-design/icons-vue";
 import type { PropType } from "vue";
 
 const props = defineProps({
   data: {
     type: Object as PropType<ChapterSearchDocResponse>,
     required: true
+  },
+  used: {
+    type: Boolean,
+    required: false,
   }
 });
 
 const emits = defineEmits<{
   (e: "insert", text: string): void;
+  (e: "recordUse", sectionId: number): void;
+  (e: "recordCancel", sectionid: number): void;
 }>();
 
 const clipboard = useClipboard()
@@ -27,6 +34,14 @@ function getSelectedText() {
   return null
 }
 
+function onRecordUse() {
+  emits("recordUse", props.data.id)
+}
+
+function onRecordCancel() {
+  emits("recordCancel", props.data.id)
+}
+
 function onCopy() {
   const selectedText = getSelectedText()
   const text = selectedText || props.data.content
@@ -52,12 +67,14 @@ function onInsertion() {
       </span>
     </a-space>
   </div>
-  <div class="content">
+  <div class="content" :class="{'used': used}">
+    <exclamation-circle-filled v-if="used" />
     {{ data.content }}
   </div>
   <div class="btn-group">
     <a-radio-group>
-      <a-radio-button value="large">标记使用</a-radio-button>
+      <a-radio-button value="large" @click="onRecordUse" v-if="!used">标记使用</a-radio-button>
+      <a-radio-button value="large" @click="onRecordCancel" v-if="used">取消标记</a-radio-button>
       <a-radio-button value="default" @mousedown="onCopy">复制</a-radio-button>
       <a-radio-button value="small" @mousedown="onInsertion">插入</a-radio-button>
     </a-radio-group>
@@ -67,6 +84,10 @@ function onInsertion() {
 <style scoped lang="scss">
 .content {
   margin-top: 0.5em;
+
+  &.used {
+    color: #bebebe;
+  }
 }
 .btn-group {
   margin-top: 0.8em;

+ 0 - 1
src/views/reportPreview/ReportPreviewView.vue

@@ -1,6 +1,5 @@
 <!--报告预览视图-->
 <script setup lang="ts">
-import dayjs from 'dayjs';
 import { onMounted, ref } from 'vue';
 import { useRoute } from "vue-router";
 import * as reportService from "@/services/report.service"