OADefense1.vue 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. <template>
  2. <div class="height_100 OADefense">
  3. <conversationRecords v-show="showMenu" name="OA答辩" :show_add="false" :conversation="currentConversation" :confessionSessionList="confessionSessionList" @addConversation="addConversation" @changeConversation="changeConversation" @updateConversation="queryConfessionSession" ></conversationRecords>
  4. <!-- 左侧文件展示 -->
  5. <div class="left customize_file" v-show="showLeft">
  6. <div class="head">
  7. <div class="head_left">
  8. <div class="margin-right_10">
  9. <i v-show="showMenu" class="el-icon-s-fold" @click="showMenu = !showMenu"></i>
  10. <i v-show="!showMenu" class="el-icon-s-unfold" @click="showMenu = !showMenu"></i>
  11. </div>
  12. <div style="font-weight:600">OA答辩</div>
  13. <el-button size="mini" class="margin-left_10" type="primary" @click="addConversation">添加新OA答辩</el-button>
  14. <el-button v-if="notice_file.guid && !loading" class="margin-left_10" type="primary" size="mini" @click="regenerate">重新生成</el-button>
  15. </div>
  16. <div class="head_right">
  17. <el-select v-model="current_guid" size="mini" placeholder="请选择">
  18. <el-option v-if="notice_file.guid" :label="`审查意见通知书-${notice_file.originalName || notice_file.name}`" :value="notice_file.guid" @click.native="handleOptionClick(notice_file,1)"></el-option>
  19. <el-option v-if="app_file.guid" :label="`申请文件-${app_file.appNo}`" :value="app_file.guid" @click.native="handleOptionClick(app_file,2)"></el-option>
  20. <el-option v-if="modify_file.guid" :label="`修改对照页`" :value="modify_file.guid" @click.native="handleOptionClick(modify_file,4)"></el-option>
  21. <template v-if="contrast_file && contrast_file.length>0">
  22. <el-option
  23. v-for="(item,index) in contrast_file"
  24. :key="index"
  25. :label="`D${item.index}-${item.publicNo}`"
  26. :value="item.guid"
  27. @click.native="handleOptionClick(item,3)">
  28. </el-option>
  29. </template>
  30. </el-select>
  31. </div>
  32. </div>
  33. <div>
  34. <hr>
  35. </div>
  36. <!-- 输入 -->
  37. <template v-if="add">
  38. <div >
  39. <!-- <p>审查意见书:</p>
  40. <div>
  41. <el-upload
  42. ref="upload_file"
  43. class="upload-demo"
  44. drag
  45. action="#"
  46. :auto-upload="false"
  47. :limit="1"
  48. :file-list="notice_file.guid?[notice_file]:[]"
  49. :on-change="onChange"
  50. style="width: 100%"
  51. >
  52. <i class="el-icon-upload"></i>
  53. <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
  54. </el-upload>
  55. </div>
  56. <div style="padding: 10px 0;">
  57. <div><b>相关文件(申请文件和对比文件):(<span style="font-size:18px">非必填</span>)</b></div>
  58. <div style="font-size:16px;color:red">
  59. 注:
  60. <br>
  61. 1.如果上传了相关文件则优先使用上传的文件,如果不上传则系统会自动获取文件
  62. <br>
  63. 2.上传的申请文件要包含本申请号码,对比文件包含对比文件序号或者名称
  64. </div>
  65. </div>
  66. <div>
  67. <myUpload :file-list="patent_fileUrls" @on-change="onchangeFile" @on-remove="onRemove" style="height: 180px;" :autoUpload="true"></myUpload>
  68. </div> -->
  69. <div style="height:calc(100vh - 210px);overflow-y: auto;overflow-x:hidden">
  70. <div style="display:flex;align-items: center;justify-content:space-between">
  71. <p class="file_title"><i class="el-icon-star-on"></i>本次需要答复的审查意见通知书</p>
  72. <div>
  73. <el-button size="mini" class="margin-right_10" type="primary" @click="batch_upload">批量上传</el-button>
  74. </div>
  75. </div>
  76. <div class="upload_file">
  77. <div v-if="notice_file.guid" class="file_show">
  78. <myTooltip :content="notice_file.name ? notice_file.name : notice_file.originalName">
  79. <div class="noWrap file_name">
  80. <i class="el-icon-document" style="margin-right: 10px"></i>
  81. <span class="name">{{notice_file.name ? notice_file.name : notice_file.originalName}}</span>
  82. </div>
  83. </myTooltip>
  84. <div class="type">{{ notice_file.guid ? "已上传" : "待上传" }}</div>
  85. <div class="icon" @click="notice_file = {}">
  86. <i class="el-icon-close"></i>
  87. </div>
  88. </div>
  89. <el-upload
  90. v-else
  91. ref="upload_file"
  92. class="upload-demo"
  93. drag
  94. action="#"
  95. :auto-upload="false"
  96. :limit="1"
  97. :on-change="(file)=>onChange(file,'notice_file')"
  98. style="width: 100%"
  99. >
  100. <i class="el-icon-upload"></i>
  101. <div class="el-upload__text">
  102. <div><em>点击上传</em></div>
  103. <div>或将文件拖到此处上传</div>
  104. </div>
  105. </el-upload>
  106. </div>
  107. <div style="margin:25px 0;">
  108. <el-divider content-position="left">相关文件(选填)</el-divider>
  109. </div>
  110. <p class="file_title">本申请文件</p>
  111. <div class="upload_file">
  112. <div v-if="relevant_file.app_file.guid" class="file_show">
  113. <myTooltip :content="relevant_file.app_file.name ? relevant_file.app_file.name : relevant_file.app_file.originalName">
  114. <div class="noWrap file_name">
  115. <i class="el-icon-document" style="margin-right: 10px"></i>
  116. <span class="name">{{relevant_file.app_file.name ? relevant_file.app_file.name : relevant_file.app_file.originalName}}</span>
  117. </div>
  118. </myTooltip>
  119. <div class="type">{{ relevant_file.app_file.guid ? "已上传" : "待上传" }}</div>
  120. <div class="icon" @click="relevant_file.app_file = {}">
  121. <i class="el-icon-close"></i>
  122. </div>
  123. </div>
  124. <el-upload
  125. v-else
  126. ref="upload_file"
  127. class="upload-demo"
  128. drag
  129. action="#"
  130. :auto-upload="false"
  131. :limit="1"
  132. :on-change="(file)=>onChange(file,'relevant_file.app_file')"
  133. style="width: 100%"
  134. >
  135. <i class="el-icon-upload"></i>
  136. <div class="el-upload__text">
  137. <div><em>点击上传</em></div>
  138. <div>或将文件拖到此处上传</div>
  139. </div>
  140. </el-upload>
  141. </div>
  142. <p class="file_title">上一次OA的修改对照页(若有,要包含权利要求和说明书全文内容)</p>
  143. <div class="upload_file">
  144. <div v-if="relevant_file.modify_file.guid" class="file_show">
  145. <myTooltip :content="relevant_file.modify_file.name ? relevant_file.modify_file.name : relevant_file.modify_file.originalName">
  146. <div class="noWrap file_name">
  147. <i class="el-icon-document" style="margin-right: 10px"></i>
  148. <span class="name">{{relevant_file.modify_file.name ? relevant_file.modify_file.name : relevant_file.modify_file.originalName}}</span>
  149. </div>
  150. </myTooltip>
  151. <div class="type">{{ relevant_file.modify_file.guid ? "已上传" : "待上传" }}</div>
  152. <div class="icon" @click="relevant_file.modify_file = {}">
  153. <i class="el-icon-close"></i>
  154. </div>
  155. </div>
  156. <el-upload
  157. v-else
  158. ref="upload_file"
  159. class="upload-demo"
  160. drag
  161. action="#"
  162. :auto-upload="false"
  163. :limit="1"
  164. :on-change="(file)=>onChange(file,'relevant_file.modify_file')"
  165. style="width: 100%"
  166. >
  167. <i class="el-icon-upload"></i>
  168. <div class="el-upload__text">
  169. <div><em>点击上传</em></div>
  170. <div>或将文件拖到此处上传</div>
  171. </div>
  172. </el-upload>
  173. </div>
  174. <template v-if="relevant_file.contrast_file">
  175. <div>
  176. <div v-for="contrast_file in relevant_file.contrast_file" :key="'D'+contrast_file.order">
  177. <p class="file_title">对比文件D{{ contrast_file.order }}</p>
  178. <div class="upload_file">
  179. <div v-if="contrast_file.file.guid" class="file_show">
  180. <myTooltip :content="contrast_file.file.name ? contrast_file.file.name : contrast_file.file.originalName">
  181. <div class="noWrap file_name">
  182. <i class="el-icon-document" style="margin-right: 10px"></i>
  183. <span class="name">{{contrast_file.file.name ? contrast_file.file.name : contrast_file.file.originalName}}</span>
  184. </div>
  185. </myTooltip>
  186. <div class="type">{{ contrast_file.file.guid ? "已上传" : "待上传" }}</div>
  187. <div class="icon" @click="contrast_file.file = {}">
  188. <i class="el-icon-close"></i>
  189. </div>
  190. </div>
  191. <el-upload
  192. v-else
  193. ref="upload_file"
  194. class="upload-demo"
  195. drag
  196. action="#"
  197. :auto-upload="false"
  198. :limit="1"
  199. :on-change="(file)=>onChange(file,'file',contrast_file)"
  200. style="width: 100%"
  201. >
  202. <i class="el-icon-upload"></i>
  203. <div class="el-upload__text">
  204. <div><em>点击上传</em></div>
  205. <div>或将文件拖到此处上传</div>
  206. </div>
  207. </el-upload>
  208. </div>
  209. </div>
  210. <div class="addContrastFile">
  211. <el-button size="medium" @click="add_contrast_file">添加 + </el-button>
  212. </div>
  213. </div>
  214. </template>
  215. </div>
  216. <hr style="margin:15px 0;">
  217. <div class="run">
  218. <div></div>
  219. <el-button type="primary" size="small" @click="run"><div class="btn_content"><i class="el-icon-caret-right"></i>运行</div></el-button>
  220. </div>
  221. </div>
  222. </template>
  223. <template v-else-if="show">
  224. <vabOnlyOffice :option='option'></vabOnlyOffice>
  225. </template>
  226. <hr>
  227. </div>
  228. <!-- 中间的线 -->
  229. <div class="line" v-show="showLeft"></div>
  230. <!-- 右侧发明点和对话框 -->
  231. <div class="right" :style="!showLeft?'width:calc(100% - 0px) !important':''">
  232. <div>
  233. <div class="head">
  234. <div class="head_left">
  235. <div class="margin-right_10">
  236. <i v-show="showLeft" title="收起左侧内容" class="el-icon-s-fold" @click="showLeft = !showLeft"></i>
  237. <i v-show="!showLeft" title="展开左侧内容" class="el-icon-s-unfold" @click="showLeft = !showLeft"></i>
  238. </div>
  239. <div class="style_starIcon__t_QZN">
  240. <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
  241. <path d="M3.66699 1.33366C3.66699 0.965469 3.36852 0.666992 3.00033 0.666992C2.63214 0.666992 2.33366 0.965469 2.33366 1.33366V2.33366H1.33366C0.965469 2.33366 0.666992 2.63214 0.666992 3.00033C0.666992 3.36852 0.965469 3.66699 1.33366 3.66699H2.33366V4.66699C2.33366 5.03518 2.63214 5.33366 3.00033 5.33366C3.36852 5.33366 3.66699 5.03518 3.66699 4.66699V3.66699H4.66699C5.03518 3.66699 5.33366 3.36852 5.33366 3.00033C5.33366 2.63214 5.03518 2.33366 4.66699 2.33366H3.66699V1.33366Z" fill="#444CE7"/>
  242. <path d="M3.66699 11.3337C3.66699 10.9655 3.36852 10.667 3.00033 10.667C2.63214 10.667 2.33366 10.9655 2.33366 11.3337V12.3337H1.33366C0.965469 12.3337 0.666992 12.6321 0.666992 13.0003C0.666992 13.3685 0.965469 13.667 1.33366 13.667H2.33366V14.667C2.33366 15.0352 2.63214 15.3337 3.00033 15.3337C3.36852 15.3337 3.66699 15.0352 3.66699 14.667V13.667H4.66699C5.03518 13.667 5.33366 13.3685 5.33366 13.0003C5.33366 12.6321 5.03518 12.3337 4.66699 12.3337H3.66699V11.3337Z" fill="#444CE7"/>
  243. <path d="M9.28922 1.76101C9.1902 1.50354 8.94284 1.33366 8.66699 1.33366C8.39114 1.33366 8.14378 1.50354 8.04476 1.76101L6.88864 4.76691C6.68837 5.28761 6.62544 5.43766 6.53936 5.55872C6.45299 5.68019 6.34686 5.78632 6.22539 5.87269C6.10432 5.95878 5.95428 6.02171 5.43358 6.22198L2.42767 7.37809C2.17021 7.47712 2.00033 7.72448 2.00033 8.00033C2.00033 8.27617 2.17021 8.52353 2.42767 8.62256L5.43358 9.77867C5.95428 9.97894 6.10432 10.0419 6.22539 10.128C6.34686 10.2143 6.45299 10.3205 6.53936 10.4419C6.62544 10.563 6.68837 10.713 6.88864 11.2337L8.04476 14.2396C8.14379 14.4971 8.39114 14.667 8.66699 14.667C8.94284 14.667 9.1902 14.4971 9.28922 14.2396L10.4453 11.2337C10.6456 10.713 10.7085 10.563 10.7946 10.4419C10.881 10.3205 10.9871 10.2143 11.1086 10.128C11.2297 10.0419 11.3797 9.97894 11.9004 9.77867L14.9063 8.62256C15.1638 8.52353 15.3337 8.27617 15.3337 8.00033C15.3337 7.72448 15.1638 7.47712 14.9063 7.37809L11.9004 6.22198C11.3797 6.02171 11.2297 5.95878 11.1086 5.87269C10.9871 5.78632 10.881 5.68019 10.7946 5.55872C10.7085 5.43766 10.6456 5.28761 10.4453 4.76691L9.28922 1.76101Z" fill="#444CE7"/>
  244. </svg>
  245. </div>
  246. <div class="title">AI 智能书写 <span v-if="loading"><i class="el-icon-loading margin-left_10"></i></span></div>
  247. </div>
  248. <div class="head_right">
  249. <el-button v-if="!loading && result && result.code != 1001 && !result_file.show" type="primary" size="mini" @click="copy">复制</el-button>
  250. <el-button v-if="!loading && result && result.code != 1001" type="primary" size="mini" :loading="btnLoading" @click="download_file">下载</el-button>
  251. </div>
  252. </div>
  253. </div>
  254. <div v-if="!result && loading" class="loading-container">
  255. <div v-if="loading_text">
  256. {{ loading_text }} <i class="el-icon-loading margin-left_10"></i>
  257. </div>
  258. <div v-else class="loading-text">
  259. <span>思</span>
  260. <span>考</span>
  261. <span>中</span>
  262. <span>.</span>
  263. <span>.</span>
  264. <span>.</span>
  265. </div>
  266. </div>
  267. <div class="result" ref="AIMessage" v-else>
  268. <template v-if="result_file.show">
  269. <vabOnlyOffice :option='result_file.option'></vabOnlyOffice>
  270. </template>
  271. <!-- 结果 -->
  272. <template v-else-if="result && result.code == 1001">
  273. <div>
  274. <div style="font-size:16px" v-html="result.data.replace('\n','<br>')"></div>
  275. <div>
  276. <el-link type="primary" @click="openErrorTip">点击上传</el-link>
  277. </div>
  278. </div>
  279. </template>
  280. <template v-else-if="result && result.code == 1002">
  281. <div>
  282. <div style="font-size:16px">
  283. {{ result.data }},请<el-link type="primary" @click="getResult">重试</el-link>
  284. </div>
  285. </div>
  286. </template>
  287. <template v-else-if="result">
  288. <div class="answer_warp">
  289. <div v-for="(item,index) in formateAIAnswer(this.result)" :key="index">
  290. <div v-if="item.type == 'text'" id='answer'>
  291. <div v-if="item.content && item.content != 'null'" v-html="renderMarkdown(item.content)"></div>
  292. </div>
  293. </div>
  294. </div>
  295. </template>
  296. <div class="jiazai" v-if="result && loading">
  297. <span style="color:red;">{{loading_text}}</span> <i class="el-icon-loading margin-left_10"></i>
  298. </div>
  299. </div>
  300. </div>
  301. <!-- 错误提示以及上传文件 -->
  302. <errorTipDialog ref="errorTip" @submit="reLoadSubmit"></errorTipDialog>
  303. <!-- 批量上传文件 -->
  304. <batchFileDialog ref="batchFile" :sign="1" @get_file_obj="get_file_obj"></batchFileDialog>
  305. </div>
  306. </template>
  307. <script>
  308. import vabOnlyOffice from '@/components/VabOnlyOffice/index.vue'
  309. import mixin from './mixins/index1.js';
  310. import conversationRecords from '../components/conversationRecords.vue';
  311. import {renderMarkdown} from '@/utils/markdown'
  312. import { downLoad2 } from '@/utils'
  313. import { scrollToBottom } from '../components/mixins/scrollToBottom'
  314. import errorTipDialog from './dialog/errorTip.vue'
  315. import batchFileDialog from './dialog/batchFile.vue';
  316. export default {
  317. components: {
  318. conversationRecords,
  319. vabOnlyOffice,
  320. errorTipDialog,
  321. batchFileDialog
  322. },
  323. props: {},
  324. mixins:[mixin,scrollToBottom],
  325. data() {
  326. return {
  327. showMenu:false,//是否显示左侧菜单
  328. showLeft:true,//展示左侧内容
  329. currentConversation:{},//当前会话
  330. confessionSessionList:[],//会话记录
  331. chat_id:null,
  332. btnLoading:false,//按钮加载
  333. loading:false,//生成中
  334. loading_text:'',
  335. result:'',//OA答辩结果文本
  336. show:false,//显示左侧文件
  337. option:{//左侧文件配置
  338. url: '',
  339. isEdit: false,
  340. fileType: '',
  341. title: '',
  342. lang: 'zh-CN',
  343. isPrint: true,
  344. user: {
  345. id: this.$s.getObj('userinfo').id,
  346. name: this.$s.getObj('userinfo').name
  347. }
  348. },
  349. confession:{},//文件信息
  350. reLoadSearch:false,//重新生成OA答辩
  351. add:true,//添加审查通知书
  352. notice_file:{},//审查通知书文件
  353. relevant_file:{
  354. app_file:{},
  355. modify_file:{},
  356. contrast_file:[
  357. {
  358. order:1,
  359. file:{}
  360. },
  361. {
  362. order:2,
  363. file:{}
  364. },
  365. {
  366. order:3,
  367. file:{}
  368. },
  369. ]
  370. },
  371. patent_fileUrls:[],//专利文件地址
  372. result_file:{},//结果文件
  373. app_file:{},//申请文件
  374. modify_file:{},//修改对照页文件
  375. contrast_file:[],//对比文件
  376. current_guid:'',//左侧当前显示的文件
  377. };
  378. },
  379. watch: {
  380. result(){
  381. this.scrollToBottom()
  382. }
  383. },
  384. computed: {},
  385. created() {
  386. this.getInit()
  387. },
  388. mounted() {},
  389. methods: {
  390. renderMarkdown,
  391. //初始化
  392. async getInit(){
  393. this.queryConfessionSession()
  394. },
  395. add_contrast_file(){
  396. let order1 = this.relevant_file.contrast_file[this.relevant_file.contrast_file.length-1].order
  397. this.relevant_file.contrast_file.push(
  398. {
  399. order:order1 + 1,
  400. file:{}
  401. }
  402. )
  403. },
  404. //批量上传
  405. batch_upload(){
  406. this.$refs.batchFile.open()
  407. },
  408. get_file_obj(data){
  409. if(data.notice_file){
  410. this.$set(this,'notice_file',data.notice_file)
  411. }
  412. if(data.app_file){
  413. this.$set(this.relevant_file,'app_file',data.app_file)
  414. }
  415. if(data.modify_file){
  416. this.$set(this.relevant_file,'modify_file',data.modify_file)
  417. }
  418. if(data.contrast_file && data.contrast_file.length>0){
  419. let contrast_file = this.relevant_file.contrast_file
  420. for(let i = 0;i<data.contrast_file.length;i++){
  421. let item = data.contrast_file[i]
  422. let order = item.order
  423. let obj = contrast_file.find(file=>{
  424. return file.order == order
  425. })
  426. if(obj){
  427. obj.file = item.file
  428. }else{
  429. let order1 = contrast_file[contrast_file.length-1].order
  430. if(order > order1 + 1){
  431. for(let y = order1 + 1;y < order;y++){
  432. contrast_file.push(
  433. {
  434. order:y,
  435. file:{}
  436. }
  437. )
  438. }
  439. }
  440. contrast_file.push(item)
  441. }
  442. }
  443. }
  444. },
  445. //再次提交
  446. reLoadSubmit(data){
  447. // if(!data || data.length==0){
  448. // return
  449. // }
  450. // for(let i = 0;i<data.length;i++){
  451. // let name = data[i].name
  452. // let index = this.patent_fileUrls.findIndex(item=>{
  453. // return item.name == name
  454. // })
  455. // if(index == -1){
  456. // this.patent_fileUrls.push(data[i])
  457. // }
  458. // }
  459. this.get_file_obj(data)
  460. let content = this.currentConversation.content
  461. var params = {
  462. confessionSessionId:this.currentConversation.id,
  463. }
  464. if(!content){
  465. params.content = JSON.stringify(
  466. {
  467. query:{
  468. // patent_fileUrls:this.patent_fileUrls,
  469. relevant_file:this.relevant_file,
  470. }
  471. }
  472. )
  473. }else{
  474. try{
  475. let data1 = JSON.parse(content)
  476. if(data1.data && data1.data.code == 1001){
  477. data1.data = {}
  478. }
  479. // if(data1.query && data1.query.patent_fileUrls){
  480. // data1.query.patent_fileUrls = this.patent_fileUrls
  481. // }else{
  482. // data1.query = {
  483. // patent_fileUrls:this.patent_fileUrls
  484. // }
  485. // }
  486. if(data1.query && data1.query.relevant_file){
  487. data1.query.relevant_file = this.relevant_file
  488. }else{
  489. data1.query = {
  490. relevant_file:this.relevant_file
  491. }
  492. }
  493. params.content = JSON.stringify(data1)
  494. }catch(e){
  495. params.content = JSON.stringify(
  496. {
  497. query:{
  498. // patent_fileUrls:this.patent_fileUrls,
  499. relevant_file:this.relevant_file
  500. }
  501. }
  502. )
  503. }
  504. }
  505. this.$api.updateConfessionSession(params).then(response=>{
  506. if(response.code == 200){
  507. this.reLoadSearch = true
  508. this.queryConfessionSession()
  509. this.getResult()
  510. }
  511. }).catch(error=>{
  512. })
  513. },
  514. //查询技术交底书会话记录
  515. queryConfessionSession(onlyQuery,request,result){
  516. var params = {
  517. type:2
  518. }
  519. this.$api.queryConfessionSession(params).then(response=>{
  520. if(response.code == 200){
  521. this.confessionSessionList = response.data || []
  522. if(!onlyQuery && this.confessionSessionList.length>0){
  523. this.add = false
  524. let obj = null
  525. if(this.currentConversation.id){
  526. obj = this.confessionSessionList.find(item=>{
  527. return item.id == this.currentConversation.id
  528. })
  529. }else{
  530. obj = this.confessionSessionList[0]
  531. }
  532. if(obj){
  533. this.changeConversation(obj,true)
  534. }
  535. }else if(this.confessionSessionList.length==0){
  536. this.addConversation()
  537. }
  538. if(request){
  539. this.getResult()
  540. }
  541. if(result){
  542. if(!this.confessionSessionList || this.confessionSessionList.length==0){
  543. return
  544. }
  545. let obj = this.confessionSessionList.find(item=>{
  546. return item.id == this.currentConversation.id
  547. })
  548. if(!obj){
  549. obj = this.confessionSessionList[0]
  550. }
  551. this.getResultContent(obj)
  552. }
  553. }
  554. })
  555. },
  556. run(){
  557. var params = {
  558. fileGuid:this.notice_file.guid,
  559. content:JSON.stringify(
  560. {
  561. query:{
  562. // patent_fileUrls:this.patent_fileUrls,
  563. relevant_file:this.relevant_file,
  564. }
  565. }
  566. ),
  567. type:2
  568. }
  569. this.$api.addConfessionSession(params).then(response=>{
  570. if(response.code == 200){
  571. //查询技术交底书会话记录
  572. this.currentConversation = {
  573. id:response.data
  574. }
  575. this.queryConfessionSession(false,true)
  576. }
  577. }).catch(error=>{
  578. message.close()
  579. })
  580. },
  581. //结果生成过程中切换、添加、刷新提示
  582. async loading_change(){
  583. var isNext = true
  584. if(this.loading){
  585. await this.$confirm('结果正在生成中,如果执行当前操作会取消当前的结果生成, 是否继续?', '提示', {
  586. confirmButtonText: '确定',
  587. cancelButtonText: '取消',
  588. type: 'warning'
  589. }).then(() => {
  590. this.cancelRun()
  591. }).catch(() => {
  592. isNext = false
  593. });
  594. }
  595. return isNext
  596. },
  597. //添加会话
  598. async addConversation(){
  599. let isNext = await this.loading_change()
  600. if(!isNext){
  601. return
  602. }
  603. this.$set(this,'currentConversation',{})
  604. this.$set(this,'confession',{})
  605. this.$set(this,'add',true)
  606. this.$set(this,'notice_file',{})
  607. // this.$set(this,'patent_fileUrls',[])
  608. this.set_relevant_file()
  609. this.$set(this,'app_file',{})
  610. this.$set(this,'contrast_file',[])
  611. this.$set(this,'result_file',{})
  612. this.$set(this,'current_guid','')
  613. this.$set(this,'result',null)
  614. this.$set(this,'loading_text','')
  615. this.$set(this,'loading',false)
  616. },
  617. //设置相关文件初始化
  618. set_relevant_file(){
  619. this.$set(this,'relevant_file',
  620. {
  621. app_file:{},
  622. modify_file:{},
  623. contrast_file:[
  624. {
  625. order:1,
  626. file:{}
  627. },
  628. {
  629. order:2,
  630. file:{}
  631. },
  632. {
  633. order:3,
  634. file:{}
  635. },
  636. ]
  637. }
  638. )
  639. },
  640. //切换左侧展示的文件
  641. handleOptionClick(obj,type){
  642. switch(type){
  643. case 1:
  644. this.confession = obj
  645. this.getOption()
  646. case 2:
  647. case 3:
  648. case 4:
  649. if(type == 2){
  650. obj.originalName = `申请文件-${obj.appNo}`
  651. }else if(type == 3){
  652. obj.originalName = `D${obj.index}-${obj.publicNo}`
  653. }else if(type == 4){
  654. obj.originalName = "修改对照页"
  655. }
  656. if(obj.type){
  657. this.confession = obj
  658. this.getOption()
  659. }else{
  660. this.getFileByGuid(obj)
  661. }
  662. break;
  663. }
  664. },
  665. //获取文件信息
  666. async getFileByGuid(obj){
  667. if(!obj.guid){
  668. this.$message.warning('当前文件不存在')
  669. return
  670. }
  671. var fileIds = [obj.guid]
  672. await this.$api.getFileData(fileIds).then(response=>{
  673. if(response && response.length>0){
  674. var data = response[0]
  675. // obj.originalName = data.originalName
  676. obj.type = data.type
  677. this.confession = obj
  678. this.getOption()
  679. }
  680. })
  681. },
  682. //切换会话
  683. async changeConversation(obj,sign){
  684. if(!sign){
  685. let isNext = await this.loading_change()
  686. if(!isNext){
  687. return
  688. }
  689. }
  690. this.add = false
  691. if(obj.id == this.currentConversation.id){
  692. this.currentConversation = obj
  693. if(sign && !this.reLoadSearch){
  694. //获取当前会话id
  695. this.chat_id = obj.conversationId
  696. this.$set(this,'current_guid',this.notice_file.guid)
  697. //装载审查意见通知书并展示
  698. this.confession = obj.systemFile || {}
  699. this.$set(this,'notice_file',JSON.parse(JSON.stringify(this.confession)))
  700. this.$set(this,'current_guid',this.notice_file.guid)
  701. this.getOption()
  702. this.reLoadSearch = false
  703. }
  704. return
  705. }
  706. //装载当前会话信息
  707. this.currentConversation = obj
  708. //获取当前会话id
  709. this.chat_id = obj.conversationId
  710. //装载审查意见通知书并展示
  711. this.confession = obj.systemFile || {}
  712. this.$set(this,'notice_file',JSON.parse(JSON.stringify(this.confession)))
  713. this.$set(this,'current_guid',this.notice_file.guid)
  714. this.getOption()
  715. //装载结果
  716. this.getResultContent(obj)
  717. },
  718. getResultContent(obj){
  719. this.result_file = {
  720. file_message:obj.assoSystemFile || {},
  721. show:false,
  722. option:{
  723. url: '',
  724. isEdit: false,
  725. fileType: '',
  726. title: '',
  727. lang: 'zh-CN',
  728. isPrint: true,
  729. user: {
  730. id: this.$s.getObj('userinfo').id,
  731. name: this.$s.getObj('userinfo').name
  732. }
  733. }
  734. }
  735. this.getResultOption()
  736. this.$set(this,'result',null)
  737. // this.$set(this,'patent_fileUrls',[])
  738. this.set_relevant_file()
  739. this.contrast_file = []
  740. this.app_file = {}
  741. let content = obj.content
  742. if(!content){
  743. // this.$set(this,'patent_fileUrls',[])
  744. this.set_relevant_file()
  745. return
  746. }
  747. try{
  748. let data = JSON.parse(content)
  749. // if(data.query && data.query.patent_fileUrls){
  750. // this.$set(this,'patent_fileUrls',data.query.patent_fileUrls)
  751. // }
  752. if(data.query && data.query.relevant_file){
  753. this.$set(this,'relevant_file',data.query.relevant_file)
  754. }
  755. if(data.answer){
  756. this.$set(this,'result',data.answer)
  757. }
  758. if(data.data){
  759. let answer_data = data.data
  760. if(answer_data.code == 200){
  761. this.app_file = answer_data.data.app_file || {}
  762. this.modify_file = answer_data.data.modify_file || {}
  763. this.contrast_file = answer_data.data.contrast_file || []
  764. if(!this.result_file.show){
  765. let num = answer_data.data.num
  766. let claim_change = answer_data.data.claim_change
  767. let defense_opinion = answer_data.data.defense_opinion || []
  768. let reason = answer_data.data.reason
  769. let html = `<div style="line-height: 1.8em;"><div style="text-align: center;"><b>意见陈述书</b></div><div style="text-indent: 2em;margin: 0;">尊敬的审查员:</div><div style="text-indent: 2em;margin: 0;">首先,感谢审查员为审查本申请而付出的艰辛劳动!</div><div style="text-indent: 2em;margin: 0;">本意见陈述书是对国家知识产权局发出的第${num}次审查意见通知书所作的答复。</div><div style="text-indent: 2em;margin: 0;">审查意见通知书中指出:${ reason }</div><div style="text-indent: 2em;margin: 0;">申请人在仔细阅读、认真研究审查员的审查意见之后,在原权利要求书的基础上对权利要求进行了修改,并陈述意见如下:</div><div style="text-indent: 2em;margin: 0;"><b>一、修改说明</b></div><div style="text-indent: 2em;margin: 0;">${claim_change}</div><div style="text-indent: 2em;margin: 0;">`
  770. defense_opinion.forEach(item => {
  771. html = html + `<p>${item}</p>`
  772. });
  773. html = html + `</div><div style="text-indent: 2em;margin: 0;">综上所述,申请人认为,经过上述对原申请文件的陈述,已克服审查员在审查意见通知书中所指出的所有缺陷,希望审查员能以此为基础继续对本发明进行审查,如果审查员认为该申请仍有不符合专利法及其实施细则规定之处,恳请再给予一次陈述意见/修改的机会。</div><div style="text-indent: 2em;margin: 0;">感谢审查员的辛勤工作。</div></div>`
  774. this.$set(this,'result',html)
  775. }
  776. }else if(answer_data.code == 1001){
  777. this.result = answer_data
  778. this.$refs.errorTip.open(answer_data)
  779. }else if(answer_data.code == 1002){
  780. this.result = answer_data
  781. }
  782. }
  783. }catch(e){
  784. }
  785. },
  786. openErrorTip(){
  787. this.$refs.errorTip.open(this.result)
  788. },
  789. setData(row,field,value){
  790. var fieldArray = field.split('.')
  791. let current = row || this;
  792. // 遍历路径中的每一部分,直到最后一个属性的父对象
  793. for (let i = 0; i < fieldArray.length - 1; i++) {
  794. // 确保当前对象有下一个属性,否则创建一个空对象(或你需要的任何默认值)
  795. if (!current.hasOwnProperty(fieldArray[i])) {
  796. current[fieldArray[i]] = {};
  797. }
  798. current = current[fieldArray[i]];
  799. }
  800. // 给最后一个属性赋值
  801. current[fieldArray[fieldArray.length - 1]] = value;
  802. },
  803. //上传文件
  804. onChange(file,field,row){
  805. let formData = new FormData()
  806. formData.append('sourceId',this.$constants.sourceId)
  807. formData.append('files',file.raw)
  808. var notice_file = {
  809. name:file.raw.name
  810. }
  811. var message = this.$message({
  812. message: '文件上传中...',
  813. type: 'warning',
  814. duration:0
  815. });
  816. this.$api.uploadFile(formData).then(response=>{
  817. if(response.code == 200){
  818. let guid = response.data[0]
  819. notice_file.guid = guid
  820. // this.$set(this,field,notice_file)
  821. this.setData(row,field,notice_file)
  822. message.close()
  823. this.$message.success('文件上传成功')
  824. }
  825. })
  826. },
  827. getOption(data,model='view'){
  828. let option_data = data || this.confession
  829. if(!option_data.guid){
  830. this.$message.warning('文件不存在')
  831. return
  832. }
  833. this.show = false
  834. this.option.name = option_data.originalName
  835. this.option.id = option_data.guid
  836. this.option.title = option_data.originalName
  837. this.option.url = this.$c.url+ (this.$c.env=='production'?'/api':'')+'/fileManager/downloadFile?fileId=' + option_data.guid
  838. this.option.fileType = option_data.type
  839. this.option.key = option_data.guid
  840. this.option.model = model
  841. this.$nextTick(()=>{
  842. this.show = true
  843. })
  844. },
  845. getResultOption(model='edit'){
  846. let option_data = this.result_file.file_message
  847. if(!option_data.guid){
  848. // this.$message.warning('文件不存在')
  849. return
  850. }
  851. let option = this.result_file.option
  852. // this.result_file.show = false
  853. this.$set(this.result_file,'show',false)
  854. option.name = option_data.originalName
  855. option.id = option_data.guid
  856. option.title = option_data.originalName
  857. option.url = this.$c.url+ (this.$c.env=='production'?'/api':'')+'/fileManager/downloadFile?fileId=' + option_data.guid
  858. option.fileType = option_data.type
  859. option.key = option_data.guid
  860. option.model = model
  861. this.$nextTick(()=>{
  862. this.$set(this.result_file,'show',true)
  863. })
  864. },
  865. //下载文件
  866. async download_file(){
  867. if(this.currentConversation.assoSystemFile && this.currentConversation.assoSystemFile.guid){
  868. downLoad2(this.currentConversation.assoSystemFile.guid,this.currentConversation.assoSystemFile.originalName)
  869. return
  870. }
  871. let confessionSessionId = this.currentConversation.id
  872. let filename = this.currentConversation.conversationName
  873. this.btnLoading = true
  874. let html = ''
  875. let answerDomList = document.querySelectorAll('#answer')
  876. if(answerDomList.length == 0){
  877. this.btnLoading = false
  878. return
  879. }
  880. let answerDom = answerDomList[answerDomList.length - 1]
  881. html = answerDom.innerHTML
  882. let guid = await this.$commonJS.exportToWordByHtml(html,filename,true)
  883. if(guid){
  884. this.saveResultFile(confessionSessionId,guid)
  885. }
  886. this.btnLoading = false
  887. },
  888. //保存下载之后的文件
  889. saveResultFile(confessionSessionId,guid){
  890. var params = {
  891. confessionSessionId:confessionSessionId,
  892. guid:guid
  893. }
  894. this.$api.addConfessionSessionFile(params).then(response=>{
  895. if(response.code == 200){
  896. this.queryConfessionSession()
  897. }
  898. })
  899. },
  900. //重新生成
  901. regenerate(){
  902. this.run()
  903. },
  904. },
  905. };
  906. </script>
  907. <style lang="scss">
  908. .OADefense{
  909. .file_title{
  910. font-weight: bold;
  911. i{
  912. color: red !important;
  913. }
  914. }
  915. .file_show{
  916. display: flex;
  917. align-items: center;
  918. justify-content: space-between;
  919. line-height: 100px;
  920. .file_name{
  921. width: calc(100% - 90px);
  922. }
  923. .type {
  924. min-width:75px;
  925. display: block;
  926. color: #57a5f7;
  927. }
  928. .icon {
  929. display: none;
  930. }
  931. }
  932. .file_show:hover {
  933. background: #f4f4f4;
  934. .name {
  935. color: #57a5f7;
  936. cursor: pointer;
  937. }
  938. .type {
  939. min-width:75px;
  940. display: none;
  941. }
  942. .icon {
  943. display: block;
  944. cursor: pointer;
  945. }
  946. }
  947. .customize_file{
  948. .upload-demo{
  949. .el-upload{
  950. width: 100% !important;
  951. }
  952. .el-upload-dragger {
  953. width: 100% !important;
  954. height:100px !important;
  955. display: flex;
  956. align-items: center;
  957. .el-icon-upload{
  958. font-size: 40px !important;
  959. margin: 0 25px !important;
  960. }
  961. }
  962. }
  963. }
  964. }
  965. </style>
  966. <style lang="scss" scoped>
  967. .OADefense{
  968. position: relative;
  969. display: flex;
  970. align-items: stretch;
  971. height: calc(100% - 20px);
  972. width:calc(100% - 20px);
  973. padding: 10px;
  974. .left{
  975. width:50%;
  976. height:calc(100% - 0px);
  977. padding-right: 10px;
  978. display: flex;
  979. flex-direction: column;
  980. .head{
  981. display: flex;
  982. align-items: center;
  983. justify-content: space-between;
  984. padding-bottom: 10px;
  985. .head_left{
  986. display: flex;
  987. align-items: center;
  988. }
  989. i{
  990. font-size: 20px;
  991. }
  992. }
  993. .addContrastFile{
  994. margin-top: 10px;
  995. display: flex;
  996. justify-content: center;
  997. width: 100%;
  998. }
  999. .run{
  1000. display: flex;
  1001. justify-content: space-between;
  1002. .btn_content{
  1003. font-size: 14px;
  1004. display: flex;
  1005. align-items: center;
  1006. i{
  1007. margin-right: 5px;
  1008. font-size: 16px;
  1009. }
  1010. }
  1011. }
  1012. }
  1013. .line{
  1014. width:2px;
  1015. height: 100%;
  1016. background: #e6e6e6;
  1017. }
  1018. .right{
  1019. width:calc(100% - 50% - 2px);
  1020. min-width: 450px;
  1021. height:100%;
  1022. padding-left: 10px;
  1023. display: flex;
  1024. flex-direction: column;
  1025. .head{
  1026. display: flex;
  1027. align-items: center;
  1028. justify-content: space-between;
  1029. .head_left,.head_right{
  1030. display: flex;
  1031. align-items: center;
  1032. }
  1033. }
  1034. .style_starIcon__t_QZN{
  1035. width: 16px;
  1036. height: 16px;
  1037. }
  1038. .title{
  1039. margin-left: 20px;
  1040. font-weight: 600;
  1041. }
  1042. .result{
  1043. margin-top: 20px;
  1044. height:calc(100% - 20px - 30px);
  1045. overflow: auto;
  1046. &:empty::after{
  1047. content: "无结果";
  1048. color:#c2c5c9;
  1049. text-align: center;
  1050. }
  1051. .jiazai{
  1052. display: flex;
  1053. align-items: center;
  1054. height: 20px;
  1055. }
  1056. }
  1057. .loading-container{
  1058. display: flex;
  1059. justify-content: center;
  1060. align-items: center;
  1061. height: 100vh;
  1062. .loading-text {
  1063. font-size: 24px;
  1064. font-family: Arial;
  1065. display: flex;
  1066. gap: 4px;
  1067. }
  1068. .loading-text span {
  1069. display: inline-block;
  1070. animation: bounce 1.2s infinite ease-in-out;
  1071. color: black;
  1072. }
  1073. .loading-text span:nth-child(2) { animation-delay: 0.1s; }
  1074. .loading-text span:nth-child(3) { animation-delay: 0.2s; }
  1075. .loading-text span:nth-child(4) { animation-delay: 0.3s; }
  1076. .loading-text span:nth-child(5) { animation-delay: 0.4s; }
  1077. @keyframes bounce {
  1078. 0%, 40%, 100% {
  1079. transform: translateY(0);
  1080. }
  1081. 20% {
  1082. transform: translateY(-15px);
  1083. }
  1084. }
  1085. }
  1086. }
  1087. }
  1088. </style>