converter.vue 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. <template>
  2. <div class="page-converter">
  3. <div class="date-tips flex content-center justify-center py-6px">
  4. <img src="http://cn-file.17pdf.com/website/common/ic_notice.svg" class="align-middle">
  5. <div class="text-container">
  6. <span class="text">
  7. 转档后的文件支持在云端保留24小时,<span v-if="userInfo?.subscriberType === 1">会员尊享5G容量,</span>请在24小时内下载文件至本地永久保存
  8. </span>
  9. <span v-if="userInfo?.subscriberType === 1" class="vip tip">
  10. <img src="http://cn-file.17pdf.com/website/common/ic_info.svg" alt="">
  11. <div class="tip-text">
  12. 若已有文件大小超出5G,将按转档时间计算(从最近一次转档往过去推算),即保留最近的5G容量文件,超出部分文件将不再保留
  13. </div>
  14. </span>
  15. </div>
  16. </div>
  17. <h1 class="text-48px text-opacity-100 font-500 text-[#3333] mt-48px mb-10px text-center">文件转换器</h1>
  18. <h2 class="text-20px text-center text-[#666] mt-20px font-normal">PDF文件格式转换器,一键转档,支持批量转换,精准快速。</h2>
  19. <div class="text-center mb-80px">
  20. <a
  21. class="mt-20px text-[#4D4D4D] text-16px font-600 inline-flex items-center leading-22px hover:text-$btn-color-primary hover:underline"
  22. href="https://www.compdf.com/pdf-conversion-sdk?utm_source=anroidapp&utm_medium=17pdfweb&utm_campaign=pdfsdk" target="_blank">由 ComPDFKit Conversion SDK 提供技术支持
  23. <svg class="ml-8px" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
  24. <path d="M6 12.9567L10.714 8.24261L6 3.52856" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
  25. </svg>
  26. </a>
  27. </div>
  28. <div class="transfer-container-wrap">
  29. <div class="index-converter w-[80%] h-700px relative top-0 left-[50%] -ml-[40%]">
  30. <div class="transfer-container absolute w-full h-auto my-0 -mx-15px bg-white pb-60px">
  31. <button type="button" class="close hidden" data-dismiss="modal" aria-label="Close">
  32. <span aria-hidden="true">×</span>
  33. </button>
  34. <div class="recharge py-0 px-[10%] h-48px mx-0 mt-24px mb-14px absolute right-0 -top-70px z-2">
  35. <span @click="handlSubmit($event, 'buy')" class="recharge-btn float-right bg-white border border-[#ff4f4f] boder-solid text-16px py-7px px-18px rounded-4px mt-4px cursor-pointer hover:bg-[#ff4f4f]">
  36. <a class="text-[#ff4f4f] no-underline leading-normal">充值</a>
  37. </span>
  38. <div class="need-volume float-right right-48px text-16px text-[#666] leading-48px mr-20px">
  39. 所需券:<span class="text-[#0dd299] text-16px" :class="{'text-red-500': requiredCoupon > userInfo?.points}">{{ requiredCoupon }}券</span> / 剩余券:<span class="text-[#0dd299] text-16px">{{ Object.keys(this.userInfo).length === 0 ? 0 : userInfo.points }}券</span>
  40. </div>
  41. </div>
  42. <div class="transfer-panel">
  43. <div>
  44. <form enctype="multipart/form-data">
  45. <input type="hidden" name="folder" value="converter/input"/>
  46. <div class="file-input theme-explorer file-input-ajax-new h-380px mt-17px py-0 px-[10%]">
  47. <div class="file-preview rounded-5px w-[100%] h-[100%]">
  48. <div class="file-drop-zone border border-dashed border-[#d1d1d1] rounded-4px h-[100%] text-center align-middle overflow-y-auto">
  49. <div v-show="fileList.length <= 0" class="file-drop-zone-title text-[#999] text-16px pt-222px cursor-default">
  50. <div></div>
  51. 点击从电脑上传文件或把文件拖到这里
  52. <p class="text-14px">(支持PDF to Word、PPT、Excel、TXT、JPG/PNG无限次数转换)</p>
  53. </div>
  54. <table id="table-fileinput" class="table table-hover w-[100%] max-w-[100%]">
  55. <thead v-show="fileList.length > 0">
  56. <tr class="h-40px bg-[#eee]">
  57. <th class="!w-[5.5%]"></th>
  58. <th class="!text-left w-[26.5%]">文档名</th>
  59. <th class="!w-[17%]">大小</th>
  60. <th class="!w-[13%]">所需券</th>
  61. <th class="!w-[9.5%]">转为</th>
  62. <th class="!w-[23%]">状态</th>
  63. <th class="!w-[4.5%]"></th>
  64. </tr>
  65. </thead>
  66. <tbody v-show="fileList.length > 0" class="file-preview-thumbnails cursor-default">
  67. <tr v-for="(item, index) in fileList" id="preview-1668340925733-0" :key="index" class="file-preview-frame explorer-frame kv-preview-thumb w-100px h-38px hover:bg-[#f5f5f5]" data-fileindex="0" data-template="pdf" title="test.pdf">
  68. <td class="file-details-cell">{{ index+1 }}</td>
  69. <td class="file-details-cell !text-left">
  70. <div class="explorer-caption max-w-260px truncate block text-[#777]" title="test.pdf">{{ item.name }}</div>
  71. </td>
  72. <td class="file-details-cell text-[#999]">{{ getfilesize(item.size) }}</td>
  73. <td class="file-details-cell points">{{ userInfo?.subscriberType === 1 ? 0 : item.price }}</td>
  74. <td class="file-details-cell select w-106px">
  75. <select v-if="item.status !== 6" v-model="item.output" class="transfer-select appearance-none text-center min-w-90px" @change="changeOutput(item, index)">
  76. <option value="png" class="text-center">PNG</option>
  77. <option value="xlsx" class="text-center">XLSX</option>
  78. <option value="pptx" class="text-center">PPTX</option>
  79. <option value="docx" class="text-center">DOCX</option>
  80. <option value="txt" class="text-center">TXT</option>
  81. <option value="jpg" class="text-center">JPG</option>
  82. </select>
  83. <span v-else>{{ item.output }}</span>
  84. </td>
  85. <td class="file-details-cell state text-14px text-[#878787]" v-html="fileStatus(item, index)"></td>
  86. <!-- <td v-else class="file-details-cell state text-14px text-red-500">转换失败<img src="/converter/menu_ic_pdfconvert.png" @click="rechangeFile" /></td> -->
  87. <td class="file-actions-cell w-50px p-0">
  88. <div class="file-actions text-center">
  89. <div class="file-footer-buttons" @click="deleteFile(index)">
  90. <button type="button" class="kv-file-remove btn btn-xs btn-default bg-inherit !border-none pr-7px py-1px pl-5px text-12px leading-normal rounded-3px" title="删除文件"><i class="pdf-removeicon"></i></button>
  91. </div>
  92. </div>
  93. </td>
  94. </tr>
  95. </tbody>
  96. </table>
  97. <div class="clearfix"></div>
  98. <div class="file-preview-status text-success text-center text-[#3c763d]"></div>
  99. </div>
  100. </div>
  101. <div class="kv-upload-progress hide">
  102. <div class="progress overflow-hidden h-20px mb-20px bg-[#f5f5f5] rounded-4px ring-inset-2 ring-[rgba(0,0,0/10%)]">
  103. <div class="progress-bar progress-bar-success progress-bar-striped active w-0 bg-[#5cb85c]" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
  104. </div>
  105. </div>
  106. <div class="input-group file-caption-main w-[100%] -top-450px relative table border-separate">
  107. <div v-if="changeFileFlag" class="input-group-btn relative text-0px whitespace-nowrap !flex">
  108. <div tabindex="500" class="btn btn-file" :class="{'btn-file-left' : fileList.length > 0}">
  109. <div class="add-file" :class="{'add-file-left':(fileList.length > 0)}">{{ fileList.length > 0 ? '添加文件' : '' }}</div>
  110. <input id="fileinput-explorer" ref="file" name="file" accept=".pdf" title="上传文件" type="file" multiple=""
  111. class="absolute top-0 right-0 p-0 m-0 min-w-[100%] h-[100%] w-90px text-right opacity-0 bg-none bg-repeat bg-scroll block outline-none border-0 cursor-pointer"
  112. @change="addFile($event)" @click="handlSubmit($event, '')"/>
  113. </div>
  114. <div v-if="fileList.length > 0" class="inline-block ml-30px bg-white border border-[#ff4f4f] boder-solid text-16px py-7px px-18px rounded-4px mt-4px cursor-pointer text-[#ff4f4f] leading-normal hover:bg-[#ff4f4f] hover:text-white" @click="deleteAllFile">清空</div>
  115. </div>
  116. </div>
  117. </div>
  118. </form>
  119. </div>
  120. <div class="transfer-btn mt-30px h-64px text-center">
  121. <div class="cursor-not-allowed inline-block">
  122. <span :class="{'disabledBtn' : !checkbox || !changeFileFlag }" class="btn transfer-start-btn bg-[#ff524f] text-20px py-0 px-150px rounded-4px h-60px w-386px text-white hover:bg-[#f34545]" @click="handlSubmit($event, 'change')">
  123. <a class="text-white leading-60px">{{ !changeFileFlag ? '转换中...' : '开始转换' }}</a>
  124. <span v-if="!changeFileFlag" class="loading"></span>
  125. </span>
  126. </div>
  127. <span class="hide btn btn-down small w-240px h-60px bg-[#0dd299] rounded-4px text-20px ml-15px hover:bg-[#0fc993]"><a class="leading-60px text-white">下载全部</a></span>
  128. </div>
  129. </div>
  130. <div class="transfer-remember mt-23px text-center">
  131. <div class="checkbox checkbox-danger relative block mt-10px mb-10px">
  132. <label for="remember" class="text-12px font-normal text-[#999] min-h-20px pl-20px mb-0 inline-block max-w-[100%]">
  133. <input v-model="checkbox" type="checkbox" name="remember" class="remember_pass cursor-pointer" :disabled="!changeFileFlag" :class="{'cursor-not-allowed' : !changeFileFlag }" />确保上传的文档不涉及版权问题及违法内容
  134. </label>
  135. </div>
  136. </div>
  137. </div>
  138. <div class="modal verifi-modal top-[20%!important]" d="verifiPayModal" tabindex="-1" role="dialog" aria-labelledby="verifiPayModal">
  139. <div class="modal-dialog verifi-dialog w-480px h-426px my-50px" role="document">
  140. <div class="modal-content relative bg-white rounded-6px border border-solid border-[rgba(0,0,0,0.2)] outline-0 bg-clip-padding ring-[rgba(0,0,0/50%)] ring-offseet-3px ring-9px md:ring-offset-5 md:ring-15px">
  141. <div class="">
  142. <button id="verifi-close" type="button" class="close pompt_close py-5px px-10px outline-none" data-dismiss="modal" aria-label="Close">
  143. <span aria-hidden="true">×</span>
  144. </button>
  145. </div>
  146. <div class="verifi-content text-center pt-60px px-0 pb-35px">
  147. <img src="http://cn-file.17pdf.com/website/converter/pic_trans_diomands.png"/>
  148. <p>该功能为付费套餐专属</p>
  149. <p>订阅解锁更多特权</p>
  150. <a href="javascript:;" class="now_pricing" value="0"
  151. >立即订阅</a
  152. >
  153. </div>
  154. </div>
  155. </div>
  156. </div>
  157. </div>
  158. <div class="file_num w-[100%] h-120px text-center text-white leading-120px text-30px mb-76px">
  159. 17PDF Reader,当前已转换了<span class="text-32px"> 1,859,726 </span> 个文件
  160. </div>
  161. <div id="more_type" class="pdf_converter clear w-[80%] my-0 mx-auto">
  162. <div class="package_type">
  163. <h3 class="text-24px text-[#333] font-normal mx-0 mt-0 mb-49px h-30px leading-30px">会员专享格式</h3>
  164. <ul class="flex justify-center w-[100%] min-w-340px p-0 mt-0 mb-10">
  165. <li>
  166. <a href="/converter">
  167. <img src="/converter/ic_pdf_word.png" />
  168. <span>PDF To Word</span>
  169. </a>
  170. </li>
  171. <li>
  172. <a href="/converter">
  173. <img src="/converter/ic_pdf_ppt.png"/>
  174. <span>PDF to PowerPoint</span>
  175. </a>
  176. </li>
  177. <li>
  178. <a href="/converter">
  179. <img src="/converter/ic_pdf_execl.png"/>
  180. <span>PDF to EXCEL</span>
  181. </a>
  182. </li>
  183. <li>
  184. <a href="/converter">
  185. <img src="/converter/ic_pdf_txt.png" />
  186. <span>PDF to TXT</span>
  187. </a>
  188. </li>
  189. <li>
  190. <a href="/converter">
  191. <img src="/converter/ic_pdf_picture.png" />
  192. <span>PDF to JPG/PNG</span>
  193. </a>
  194. </li>
  195. </ul>
  196. </div>
  197. </div>
  198. <div class="about_converter w-[100%] bg-[#fafafa] py-60px px-[10%] mt-102px">
  199. <h3 class="name text-24px text-[#333] font-normal mx-0 mt-0 mb-49px h-30px leading-30px">关于转档</h3>
  200. <ul class="clear p-0">
  201. <li>
  202. <img src="http://cn-file.17pdf.com/website/converter/ic_way.png" />
  203. <div class="content">
  204. <h3>如何转档</h3>
  205. <p>
  206. 进入“文件转换器”区域。点击下方“添加文件”选择添加本地目标文件,然后在“转为”栏选择转换目标格式,最后点击“开始转换”即可。
  207. </p>
  208. </div>
  209. </li>
  210. <li>
  211. <img
  212. src="http://cn-file.17pdf.com/website/converter/ic_quality.png"
  213. />
  214. <div class="content">
  215. <h3>领先品质</h3>
  216. <p>
  217. 行业领先的转换品质,经过转换的文件版面清晰、保持格式的一致,支持一键转档,批量转换,精准快速的文件格式转换,稳定的转换品质,是您处理转格式转换的首选。
  218. </p>
  219. </div>
  220. </li>
  221. <li>
  222. <img src="http://cn-file.17pdf.com/website/converter/ic_safe.png" />
  223. <div class="content">
  224. <h3>文件安全</h3>
  225. <p>
  226. 我们尊重每位用户的隐私信息和文件安全。转档后的文件仅在云端保留24小时,让您免去后顾之忧。
  227. </p>
  228. </div>
  229. </li>
  230. <li>
  231. <img src="http://cn-file.17pdf.com/website/converter/ic_more.png" />
  232. <div class="content">
  233. <h3>多平台支持</h3>
  234. <p>
  235. 文件格式转换器可以在所有计算机(Mac、Windows及Linux)上使用,也可下载App
  236. 17PDF Reader在移动端使用,让您在手机上也能轻松转档文件。
  237. </p>
  238. </div>
  239. </li>
  240. </ul>
  241. </div>
  242. <div class="converter_question px-[10%] pt-76px pb-60px text-center">
  243. <h3 class="name text-24px text-[#333] font-normal m-0 h-30px leading-30px text-left">常见问题</h3>
  244. <table class="w-[100%] p-0 bg-transparent">
  245. <tbody>
  246. <tr>
  247. <td>
  248. <h3>1. 支持哪些格式转换?</h3>
  249. <p>
  250. <span></span>支持PDF to
  251. Word、PPT、Excel、TXT、JPG/PNG无限次数转换
  252. </p>
  253. </td>
  254. <td>
  255. <h3>2. 为什么图片格式的文件转档效果不好?</h3>
  256. <p>
  257. 如原文件为图片格式或者通过扫描文档保存为PDF文件的,转档后的文件可能无法选取文字进行高亮等编辑。
  258. </p>
  259. </td>
  260. </tr>
  261. <tr>
  262. <td>
  263. <h3>3. 文件转档后出现乱码?</h3>
  264. <p>
  265. 如果是原文件就有乱码问题,先处理好文件再提交转档;如果原文件正常而转档后目标文件乱码,请联系我们处理。
  266. </p>
  267. </td>
  268. </tr>
  269. </tbody>
  270. </table>
  271. <a class="more w-auto h-30px leading-30px text-[#666] inline-block text-center mx-auto mt-48px mb-0 link:no-underline hover:(!border-[#ff4f4f] text-[#ff4f4f])" href="/question#convert">更多问题请查看帮助</a>
  272. </div>
  273. <div class="download_code fixed right-14px bottom-50px bg-white w-134px py-12px px-0 rounded-6px text-center ">
  274. <span class="large text-16px inline-block w-[100%] my-6px mx-0">下载APP</span>
  275. <img src="http://cn-file.17pdf.com/website/download/android_code.png" class="w-110px border-0 align-middle inline-block" />
  276. <span class="inline-block w-[100%] text-14px my-6px mx-0">使用更便捷</span>
  277. </div>
  278. </div>
  279. <el-dialog :visible.sync="visiable" :close-on-click-modal="false" :close-on-press-escape="false" width="480px" append-to-body center>
  280. <div class="changepwd-tittle">
  281. <p class="text-20px text-center text-$btn-color-primary">提示</p>
  282. </div>
  283. <div class="text-16px text-[#707070] text-center my-30px">
  284. 您还未登录或注册,请先
  285. <span class="text-$btn-color-primary cursor-pointer" @click="login">登录</span>
  286. <span class="text-$btn-color-primary cursor-pointer" @click="register">注册</span>
  287. </div>
  288. </el-dialog>
  289. </div>
  290. </template>
  291. <script>
  292. import { mapState } from 'vuex'
  293. export default {
  294. data () {
  295. return {
  296. fileList: [],
  297. uniqFileArr: [],
  298. checkbox: true,
  299. changeFileFlag: true,
  300. uploadNum: 0,
  301. getFileStatusTimer: null,
  302. changeSucesssNumTotal: 0,
  303. changeSucesssFileList: [],
  304. visiable: false
  305. }
  306. },
  307. middleware: 'user',
  308. head() {
  309. return {
  310. title: 'PDF转换器免费在线转档',
  311. meta: [
  312. {
  313. hid: 'description',
  314. content: '17PDF Reader免费提供在线PDF格式转换文件转档服务,支持PDF转word,PDF转doc,PDF转PPT,PDF转png,PDF转html,PDF转epub,PDF转xls,psd转ai等。轻松拖曳,一键转档,批量转换,支持多种常用格式相互转档。先进的转换引擎,极速转换,精准度高达99.99%。',
  315. },
  316. {
  317. name: 'keywords',
  318. content: '格式转换,文件转档,pdf convert,converter, word to pdf'
  319. }
  320. ]
  321. }
  322. },
  323. computed: {
  324. ...mapState([
  325. 'userInfo'
  326. ]),
  327. // 所需券数
  328. requiredCoupon () {
  329. let total = 0
  330. for (let i = 0; i < this.fileList.length; i++) {
  331. total += this.fileList[i].price
  332. }
  333. for (const file of this.fileList) {
  334. if (file.status === 6) {
  335. total -= file.price
  336. }
  337. }
  338. if (this.userInfo && this.userInfo.subscriberType === 1) {
  339. total = 0
  340. }
  341. return total
  342. }
  343. },
  344. mounted () {
  345. console.log(this.userInfo)
  346. if (localStorage.getItem('file') !== null) {
  347. this.fileList = JSON.parse(localStorage.getItem('file'))
  348. this.changeSucesssFileList = JSON.parse(localStorage.getItem('file'))
  349. }
  350. },
  351. methods: {
  352. handlSubmit(event, type) {
  353. if (!this.$store.state.token) {
  354. event.preventDefault()
  355. this.visiable = true
  356. return
  357. }
  358. if (type === 'buy') {
  359. this.handlerBuy('ticket')
  360. } else if (type === 'change') {
  361. this.createFileMission()
  362. }
  363. // this.$store.commit('OPEN_LOGIN', true)
  364. // this.$store.commit('SET_INTERFACE', 'vip')
  365. },
  366. login() {
  367. this.visiable = false
  368. this.$store.commit('OPEN_LOGIN', true)
  369. this.$store.commit('SET_INTERFACE', 'login')
  370. },
  371. register() {
  372. this.visiable = false
  373. this.$store.commit('OPEN_LOGIN', true)
  374. this.$store.commit('SET_INTERFACE', 'register')
  375. },
  376. // 充值弹框
  377. handlerBuy(type) {
  378. this.$store.commit('OPEN_LOGIN', true)
  379. this.$store.commit('SET_INTERFACE', type)
  380. },
  381. // 添加文件
  382. async addFile (event) {
  383. // 阻止发生默认行为
  384. event.preventDefault()
  385. const array = event.target.files
  386. const defaultPrice = await this.getFilePrice('pdf', 'docx')
  387. for (let i = 0; i < array.length; i++) {
  388. const fileObj = {
  389. name: array[i].name,
  390. size: array[i].size,
  391. price: defaultPrice,
  392. input: 'pdf',
  393. output: 'docx',
  394. status: 0
  395. }
  396. this.fileList.push(fileObj)
  397. this.uniqFileArr.push(array[i])
  398. }
  399. console.log('fileList:', this.fileList)
  400. console.log('uniqFileArr:', this.uniqFileArr)
  401. },
  402. // 查询文件所需券数
  403. async getFilePrice (input, output) {
  404. let price = 0
  405. await this.$axios.get(`/convertType/getConvertTypeList?input=${input}&output=${output}`).then((res) => {
  406. if(res.code === 200) {
  407. price = res.result[0].price
  408. }
  409. })
  410. return price
  411. },
  412. // 改变要转换的格式
  413. async changeOutput (item, index) {
  414. const price = await this.getFilePrice(item.input, item.output)
  415. this.$set(this.fileList[index], 'price', price)
  416. this.$set(this.fileList[index], 'output', item.output)
  417. },
  418. // 计算文件大小函数(保留两位小数),Size为字节大小
  419. getfilesize (size) {
  420. if (!size) return ""
  421. const num = 1024.00 // byte
  422. if (size < num) {
  423. return size + "B"
  424. }
  425. if (size < Math.pow(num, 2)) {
  426. return (size / num).toFixed(2) + "K"
  427. }
  428. if (size < Math.pow(num, 3)) {
  429. return (size / Math.pow(num, 2)).toFixed(2) + "M"
  430. }
  431. if (size < Math.pow(num, 4)) {
  432. return (size / Math.pow(num, 3)).toFixed(2) + "G"
  433. }
  434. else {
  435. return (size / Math.pow(num, 4)).toFixed(2) + "T"
  436. }
  437. },
  438. // 删除文件
  439. deleteFile (index) {
  440. this.fileList.splice(index, 1)
  441. this.uniqFileArr.splice(index-this.changeSucesssNumTotal, 1)
  442. this.changeSucesssFileList = []
  443. localStorage.removeItem('file')
  444. this.fileList.forEach(item => {
  445. if (item.status === 6) {
  446. this.changeSucesssFileList.push(item)
  447. }
  448. })
  449. localStorage.setItem('file', JSON.stringify(this.changeSucesssFileList))
  450. },
  451. // 清空
  452. deleteAllFile () {
  453. this.fileList = []
  454. this.uniqFileArr = []
  455. this.changeFileStatus('all', 5)
  456. this.changeSucesssFileList = []
  457. localStorage.removeItem('file')
  458. },
  459. // 转档第一步,根据文件列表创建任务和插入文件信息
  460. createFileMission () {
  461. // if (this.fileList.length === 0) return
  462. const points = this.userInfo.points
  463. if (this.requiredCoupon > points) {
  464. alert('券数不足,请充值')
  465. return
  466. }
  467. const filterFileList = this.fileList.filter(function(item){
  468. return item.status !== 6
  469. })
  470. let fileArr = []
  471. for (let i = 0; i < filterFileList.length; i++) {
  472. const file = {}
  473. file.sourceType = 0
  474. file.size = filterFileList[i].size
  475. file.input = 'pdf'
  476. file.output = filterFileList[i].output
  477. file.filename = filterFileList[i].name
  478. fileArr[i] = file;
  479. }
  480. fileArr = JSON.stringify(fileArr)
  481. this.changeFileFlag = false
  482. this.changeFileStatus('all', 1)
  483. const config = {
  484. method: 'post',
  485. url: '/mission/create',
  486. headers: {
  487. 'Accept': '*/*',
  488. 'Content-Type': 'application/json'
  489. },
  490. data: fileArr
  491. }
  492. this.$axios('/mission/create', config).then((res) => {
  493. if(res.code === 200) {
  494. const missionFiles = res.result.missionFilePoJos
  495. console.log(missionFiles)
  496. for (let i = 0; i < missionFiles.length; i++) {
  497. this.changeFileStatus(missionFiles[i].fileName, 1)
  498. this.uploadFile(this.uniqFileArr[i], missionFiles[i].id, res.result.id)
  499. }
  500. } else {
  501. this.changeFileFlag = true
  502. this.changeFileStatus('all', 5)
  503. }
  504. })
  505. },
  506. // 修改文件状态
  507. changeFileStatus (fileName, status) {
  508. if (fileName === 'all') {
  509. this.fileList.forEach(item => {
  510. if (item.status !== 6) {
  511. this.$set(item, 'status', status)
  512. }
  513. })
  514. } else {
  515. this.fileList.forEach(item => {
  516. if (item.name === fileName) {
  517. this.$set(item, 'status', status)
  518. }
  519. })
  520. }
  521. },
  522. // 文件状态: 0未转换,1上传中,2上传完成,3转换中,4转换成功,5转换失败,6已转档
  523. fileStatus (item, index) {
  524. switch (item.status) {
  525. case 0:
  526. this.$set(this.fileList[index], 'status', 0)
  527. return '未转换'
  528. case 1:
  529. this.$set(this.fileList[index], 'status', 1)
  530. return '上传中'
  531. case 2:
  532. this.$set(this.fileList[index], 'status', 2)
  533. return '上传完成'
  534. case 3:
  535. this.$set(this.fileList[index], 'status', 3)
  536. return '转换中'
  537. case 4:
  538. this.$set(this.fileList[index], 'status', 4)
  539. return '<span style="color: orange">转换成功</span>'
  540. case 5:
  541. this.$set(this.fileList[index], 'status', 5)
  542. return '<span style="color: red">转换失败</span>'
  543. case 6:
  544. this.$set(this.fileList[index], 'status', 6)
  545. return `<a href="${item.path}" style="color: #0dd299">下载</a>`
  546. }
  547. },
  548. // 转档第二步,上传文件
  549. uploadFile (file, id, missionId) {
  550. console.log(file)
  551. this.uploadNum = 0
  552. const formData = new FormData()
  553. formData.append('file', file)
  554. formData.append('missionFileId', id)
  555. const config = {
  556. headers: {
  557. 'Content-Type': 'multipart/form-data;boundary = ' + new Date().getTime()
  558. }
  559. }
  560. this.$axios.post('/missionFile/upload', formData, config).then((res) => {
  561. console.log('上传文件')
  562. if(res.code === 200) {
  563. this.changeFileStatus(file.name, 2)
  564. this.uploadNum++
  565. if (this.uploadNum === this.uniqFileArr.length) {
  566. this.convertFile(file.name, missionId)
  567. }
  568. } else {
  569. this.changeFileFlag = true
  570. this.changeFileStatus(file.name, 5)
  571. }
  572. })
  573. },
  574. // 转档第三步,开始转档
  575. convertFile (file, missionId) {
  576. const formData = new FormData()
  577. formData.append('missionId', missionId)
  578. const config = {
  579. headers: {
  580. 'Content-Type': 'multipart/form-data;boundary = ' + new Date().getTime()
  581. }
  582. }
  583. this.$axios.post('/mission/convertFile', formData, config).then((res) => {
  584. console.log('开始转档')
  585. if(res.code === 200) {
  586. this.changeFileStatus('all', 3)
  587. this.getFileStatusTimer = window.setInterval(() => {
  588. setTimeout(this.getFileStatus(formData, config), 0)
  589. }, 3000)
  590. } else {
  591. this.uploadNum = 0
  592. this.changeFileStatus('all', 5)
  593. this.changeFileFlag = true
  594. }
  595. })
  596. },
  597. // 转档最后一步,轮询文件状态和下载链接
  598. getFileStatus (formData, config) {
  599. this.$axios.post('/mission/queryFileStatus', formData, config).then((res) => {
  600. console.log('获取文件状态')
  601. if(res.code === 200) {
  602. const getFileList = res.result[0].missionFilePoJos
  603. console.log(getFileList)
  604. let changeSucesssNum = 0
  605. for (let i = 0; i < getFileList.length; i++) {
  606. if (getFileList[i].status === 2) {
  607. this.changeFileStatus(getFileList[i].fileName, 4)
  608. this.fileList.forEach(item => {
  609. if (item.name === getFileList[i].fileName) {
  610. this.changeFileStatus(getFileList[i].fileName, 6)
  611. this.$set(item, 'path', getFileList[i].path)
  612. this.changeSucesssFileList.push(item)
  613. }
  614. })
  615. } else {
  616. this.changeFileStatus(getFileList[i].fileName, 5)
  617. }
  618. changeSucesssNum++
  619. }
  620. if (changeSucesssNum === getFileList.length) {
  621. clearInterval(this.getFileStatusTimer)
  622. this.getFileStatusTimer = null
  623. this.changeSucesssNumTotal += changeSucesssNum
  624. let failedFileList = getFileList.filter((val) => val.status === 3)
  625. let failedFileNameArr = failedFileList.map(val => val.fileName)
  626. let result = []
  627. for (let i = 0; i < failedFileNameArr.length; i++) {
  628. this.uniqFileArr.forEach(item => {
  629. if (item.name === failedFileNameArr[i]) {
  630. result.push(item)
  631. }
  632. })
  633. }
  634. this.uniqFileArr = result
  635. }
  636. console.log('changeSucesssFileList:', this.changeSucesssFileList)
  637. localStorage.setItem('file', JSON.stringify(this.changeSucesssFileList))
  638. } else {
  639. this.changeFileStatus('all', 5)
  640. }
  641. this.uploadNum = 0
  642. this.changeFileFlag = true
  643. })
  644. }
  645. }
  646. }
  647. </script>
  648. <style lang="scss" scoped>
  649. ::v-deep body {
  650. min-width: 1200px !important;
  651. }
  652. .page-converter {
  653. .date-tips {
  654. background: linear-gradient(0deg, #fff2f6, #fff2f6),
  655. linear-gradient(90deg, snow 10.37%, rgba(255, 243, 243, 0) 91.75%),
  656. linear-gradient(90deg, #fff2f6 2.26%, rgba(255, 242, 246, 0.21) 101.41%);
  657. .text-container {
  658. display: flex;
  659. align-items: center;
  660. margin-left: 16px;
  661. img {
  662. margin-left: 8px;
  663. }
  664. }
  665. span {
  666. font-size: 14px;
  667. line-height: 24px;
  668. vertical-align: middle;
  669. }
  670. .text {
  671. display: inline-flex;
  672. align-items: center;
  673. }
  674. .tip {
  675. position: relative;
  676. font-size: 0;
  677. .tip-text {
  678. display: none;
  679. position: absolute;
  680. left: -3px;
  681. width: 258px;
  682. padding: 15px 14px 10px 10px;
  683. background: url('http://cn-file.17pdf.com/website/members/ic_tip.svg')
  684. left top no-repeat;
  685. background-size: auto 100%;
  686. font-size: 12px;
  687. line-height: 18px;
  688. color: #fff;
  689. border-radius: 4px;
  690. }
  691. &:hover .tip-text {
  692. display: block;
  693. }
  694. }
  695. }
  696. .transfer-container {
  697. .hide {
  698. display: none !important;
  699. }
  700. button {
  701. padding-right: 7px;
  702. }
  703. .close {
  704. float: right;
  705. font-size: 21px;
  706. font-weight: bold;
  707. line-height: 1;
  708. color: #000;
  709. text-shadow: 0 1px 0 #fff;
  710. opacity: 0.2;
  711. filter: alpha(opacity=20);
  712. }
  713. button.close {
  714. padding: 0;
  715. cursor: pointer;
  716. background: transparent;
  717. border: 0;
  718. -webkit-appearance: none;
  719. }
  720. button:focus {
  721. outline: none;
  722. }
  723. .close:hover,
  724. .close:focus {
  725. color: #000;
  726. text-decoration: none;
  727. cursor: pointer;
  728. opacity: 0.5;
  729. filter: alpha(opacity=50);
  730. }
  731. .recharge .recharge-btn:hover a {
  732. color: #fff;
  733. }
  734. .transfer-btn .loading {
  735. display: inline-block;
  736. border: 3px solid #fff;
  737. border-bottom: 3px solid #cccccc;
  738. height: 35px;
  739. width: 35px;
  740. border-radius: 50%;
  741. position: relative;
  742. top: 10px;
  743. left: 100px;
  744. -webkit-animation: loading 1s infinite linear;
  745. -moz-animation: loading 1s infinite linear;
  746. -o-animation: loading 1s infinite linear;
  747. animation: loading 1s infinite linear;
  748. }
  749. }
  750. .table>caption+thead>tr:first-child>th, .table>caption+thead>tr:first-child>td, .table>colgroup+thead>tr:first-child>th, .table>colgroup+thead>tr:first-child>td, .table>thead:first-child>tr:first-child>th, .table>thead:first-child>tr:first-child>td {
  751. border-top: 0;
  752. }
  753. .file-drop-zone .table thead tr th {
  754. color: #666666;
  755. text-align: center;
  756. }
  757. .table>thead>tr>th {
  758. vertical-align: bottom;
  759. border-bottom: 2px solid #ddd;
  760. }
  761. .table>thead>tr>th, .table>thead>tr>td, .table>tbody>tr>th, .table>tbody>tr>td, .table>tfoot>tr>th, .table>tfoot>tr>td {
  762. padding: 8px;
  763. line-height: 1.428571429;
  764. vertical-align: top;
  765. border-top: 1px solid #ddd;
  766. }
  767. .table th, .table td {
  768. vertical-align: middle;
  769. box-sizing: border-box;
  770. }
  771. th {
  772. text-align: left;
  773. }
  774. td, th {
  775. padding: 0;
  776. }
  777. .input-group-btn {
  778. position: relative;
  779. font-size: 0;
  780. white-space: nowrap;
  781. }
  782. .input-group-addon, .input-group-btn {
  783. white-space: nowrap;
  784. vertical-align: middle;
  785. }
  786. .input-group-addon, .input-group-btn, .input-group .form-control {
  787. display: table-cell;
  788. }
  789. .clearfix:before, .clearfix:after {
  790. content: " ";
  791. display: table;
  792. }
  793. .input-group-btn:last-child>.btn, .input-group-btn:last-child>.btn-group {
  794. z-index: 2;
  795. margin-left: -1px;
  796. }
  797. .input-group-btn:first-child>.btn, .input-group-btn:first-child>.btn-group {
  798. margin-right: -1px;
  799. }
  800. .input-group .form-control:last-child, .input-group-addon:last-child, .input-group-btn:last-child>.btn, .input-group-btn:last-child>.btn-group>.btn, .input-group-btn:last-child>.dropdown-toggle, .input-group-btn:first-child>.btn:not(:first-child), .input-group-btn:first-child>.btn-group:not(:first-child)>.btn {
  801. border-bottom-left-radius: 0;
  802. border-top-left-radius: 0;
  803. }
  804. .input-group .form-control:first-child, .input-group-addon:first-child, .input-group-btn:first-child>.btn, .input-group-btn:first-child>.btn-group>.btn, .input-group-btn:first-child>.dropdown-toggle, .input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle), .input-group-btn:last-child>.btn-group:not(:last-child)>.btn {
  805. border-bottom-right-radius: 0;
  806. border-top-right-radius: 0;
  807. }
  808. .input-group-btn>.btn {
  809. position: relative;
  810. }
  811. .btn.disabled, .btn[disabled], fieldset[disabled] .btn {
  812. cursor: not-allowed;
  813. opacity: 0.65;
  814. filter: alpha(opacity=65);
  815. -webkit-box-shadow: none;
  816. box-shadow: none;
  817. }
  818. .btn-file {
  819. position: relative;
  820. overflow: hidden;
  821. margin: 0;
  822. top: 170px;
  823. left: 50%;
  824. margin-left: -45px !important;
  825. outline: none;
  826. cursor: pointer;
  827. }
  828. .btn {
  829. display: inline-block;
  830. margin-bottom: 0;
  831. font-weight: normal;
  832. text-align: center;
  833. vertical-align: middle;
  834. touch-action: manipulation;
  835. cursor: pointer;
  836. background-image: none;
  837. border: 1px solid transparent;
  838. white-space: nowrap;
  839. border-radius: 4px;
  840. -webkit-user-select: none;
  841. -moz-user-select: none;
  842. -ms-user-select: none;
  843. user-select: none;
  844. }
  845. .btn-file .add-file {
  846. background: url(http://cn-file.17pdf.com/website/fileinput/ic_file_add.png) no-repeat;
  847. width: 90px;
  848. height: 100px;
  849. }
  850. .btn-file .add-file-left {
  851. background: url(http://cn-file.17pdf.com/website/fileinput/ic_add.png) no-repeat;
  852. width: 120px;
  853. height: 30px;
  854. margin-top: 10px;
  855. margin-left: 10px;
  856. padding-left: 38px;
  857. font-size: 16px;
  858. line-height: 30px;
  859. color: #666666;
  860. }
  861. .btn-file-left {
  862. position: relative;
  863. top: 0px;
  864. left: 20px;
  865. }
  866. .transfer-container .transfer-remember .checkbox input[type="checkbox"] {
  867. top: 3px;
  868. }
  869. .radio input[type="radio"], .radio-inline input[type="radio"], .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] {
  870. position: absolute;
  871. margin-left: -20px;
  872. }
  873. input[type="radio"], input[type="checkbox"] {
  874. margin: 4px 0 0;
  875. line-height: normal;
  876. }
  877. .modal {
  878. display: none;
  879. overflow: hidden;
  880. position: fixed;
  881. top: 0;
  882. right: 0;
  883. bottom: 0;
  884. left: 0;
  885. z-index: 1050;
  886. -webkit-overflow-scrolling: touch;
  887. outline: 0;
  888. }
  889. .file-drop-zone .table tbody tr:hover td {
  890. background: #dfdfdf;
  891. }
  892. .file-drop-zone .table tbody tr td {
  893. border-top: 0px;
  894. }
  895. .theme-explorer .explorer-frame td {
  896. vertical-align: middle;
  897. text-align: center;
  898. }
  899. .file-drop-zone .table tbody tr:hover td .transfer-select {
  900. border-color: #ff4f4f;
  901. background: url(http://cn-file.17pdf.com/website/converter/ic_trans_xiala_hover.png) no-repeat 72px 6px;
  902. }
  903. .file-drop-zone .table tbody tr .transfer-select {
  904. width: 100%;
  905. height: 22px;
  906. border: 1px solid #dadada;
  907. padding: 0px;
  908. outline: none;
  909. font-size: 14px;
  910. color: #ff4f4f;
  911. line-height: 22px;
  912. // padding-left: 30px;
  913. border-radius: 2px;
  914. background: url(http://cn-file.17pdf.com/website/converter/ic_trans_xiala_nor.png) no-repeat 72px 6px;
  915. }
  916. .theme-explorer .file-actions-cell .file-actions .file-footer-buttons .pdf-removeicon:before {
  917. content: url(https://cn-file.17pdf.com/website/converter/ic_delet_red.png) !important;
  918. display: none;
  919. }
  920. .file-drop-zone .table tbody tr:hover td .file-actions .file-footer-buttons .pdf-removeicon:before {
  921. display: block;
  922. }
  923. .btn.disabledBtn {
  924. background-color: rgb(204, 204, 204);
  925. pointer-events: none;
  926. }
  927. .file_num {
  928. background: url(http://cn-file.17pdf.com/website/converter/pic_account_bg.png) repeat -10px 0px;
  929. }
  930. .clear {
  931. zoom: 1;
  932. }
  933. .clear:after {
  934. visibility: hidden;
  935. display: block;
  936. font-size: 0;
  937. content: " ";
  938. clear: both;
  939. height: 0;
  940. }
  941. .pdf_converter .package_type h3:before,
  942. .about_converter .name:before,
  943. .converter_question .name:before {
  944. content: '';
  945. display: inline-block;
  946. width: 5px;
  947. height: 22px;
  948. background: #ff4f4f;
  949. margin-right: 10px;
  950. margin-top: 4px;
  951. vertical-align: top;
  952. }
  953. .pdf_converter .package_type ul li {
  954. width: 120px;
  955. list-style: none;
  956. text-align: center;
  957. margin-right: 30px;
  958. cursor: pointer;
  959. a {
  960. display: block;
  961. font-size: 14px;
  962. color: #333333;
  963. img {
  964. display: inline-block;
  965. width: 80px;
  966. height: 80px;
  967. margin-bottom: 20px;
  968. vertical-align: middle;
  969. }
  970. span {
  971. display: block;
  972. white-space: nowrap;
  973. transition: all .5s;
  974. }
  975. }
  976. }
  977. .about_converter ul li {
  978. width: 50%;
  979. float: left;
  980. list-style: none;
  981. margin-bottom: 85px;
  982. img {
  983. width: 70px;
  984. height: 70px;
  985. float: left;
  986. margin: 10px 36px 0px 0px;
  987. }
  988. .content {
  989. width: 330px;
  990. float: left;
  991. h3 {
  992. font-size: 20px;
  993. color: #333333;
  994. margin: 0px 0px 10px;
  995. font-weight: normal;
  996. }
  997. p {
  998. font-size: 16px;
  999. color: #4c4c4c;
  1000. margin: 0px !important;
  1001. }
  1002. }
  1003. }
  1004. table {
  1005. border-collapse: collapse;
  1006. border-spacing: 0;
  1007. }
  1008. .converter_question table td {
  1009. width: 50%;
  1010. vertical-align: top;
  1011. h3 {
  1012. font-size: 18px;
  1013. color: #333333;
  1014. margin: 54px 0px 14px;
  1015. font-weight: normal;
  1016. text-align: left;
  1017. }
  1018. p {
  1019. width: 75%;
  1020. font-size: 16px;
  1021. color: #4c4c4c;
  1022. text-align: left;
  1023. span {
  1024. width: 8px;
  1025. height: 8px;
  1026. display: inline-block;
  1027. border-radius: 100%;
  1028. background: #333333;
  1029. margin-right: 12px;
  1030. margin-left: 4px;
  1031. }
  1032. }
  1033. }
  1034. .converter_question .more {
  1035. border-bottom: 1px solid #999999;
  1036. }
  1037. .download_code {
  1038. box-shadow: 0px 1px 5px rgb(0 0 0 / 12%);
  1039. }
  1040. .file-details-cell.state img {
  1041. display: inline-block;
  1042. cursor: pointer;
  1043. }
  1044. }
  1045. </style>