452 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
		
		
			
		
	
	
			452 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
|  | <!DOCTYPE html> | |||
|  | <html lang="en"> | |||
|  |   <head> | |||
|  |     <meta charset="UTF-8" /> | |||
|  |     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
|  |     <meta http-equiv="X-UA-Compatible" content="ie=edge" /> | |||
|  |     <meta name="baidu-site-verification" content="codeva-bhaFvYlfgd" /> | |||
|  |     <meta | |||
|  |       name="keywords" | |||
|  |       content="deepl、deepl翻译、百度翻译、谷歌翻译、腾讯翻译君" | |||
|  |     /> | |||
|  |     <meta | |||
|  |       name="description" | |||
|  |       content="翻译之家提供即时免费的中文、英语、日语、韩语、法语、德语、俄语、西班牙语、葡萄牙语、越南语、印尼语、意大利语、荷兰语、泰语全文翻译等服务。" | |||
|  |     /> | |||
|  |     <meta name="baidu-site-verification" content="codeva-mXz3BqI9VN" /> | |||
|  |     <link rel="stylesheet" href="static/css/public.css" /> | |||
|  |     <link rel="stylesheet" href="static/css/layui.css" /> | |||
|  |     <script src="static/js/jquery-1.11.0.min.js"></script> | |||
|  |     <script src="static/js/axios.min.js"></script> | |||
|  |     <script src="static/js/countUp.min.js"></script> | |||
|  |     <script src="static/js/vue.js"></script> | |||
|  |     <script src="static/js/lodash.min.js"></script> | |||
|  |     <script src="static/js/layui.all.js"></script> | |||
|  |     <script src="static/js/common.js"></script> | |||
|  |     <title>翻译之家</title> | |||
|  |     <script> | |||
|  |       var _hmt = _hmt || []; | |||
|  |       (function () { | |||
|  |         var hm = document.createElement("script"); | |||
|  |         hm.src = "https://hm.baidu.com/hm.js?c4e0dd6add63dd71fa52870120ca22cf"; | |||
|  |         var s = document.getElementsByTagName("script")[0]; | |||
|  |         s.parentNode.insertBefore(hm, s); | |||
|  |       })(); | |||
|  |     </script> | |||
|  |   </head> | |||
|  |   <body> | |||
|  |     <div class="public-header normal" id="main"> | |||
|  |       <div class="container clearfix"> | |||
|  |         <div class="left"> | |||
|  |           <img class="logo default" src="static/picture/logo.png" alt="" /><img | |||
|  |             class="logo1 default" | |||
|  |             src="static/picture/logo1.png" | |||
|  |             alt="" | |||
|  |           /><img class="logo light" src="static/picture/logow.png" alt="" /><img | |||
|  |             class="logo1 light" | |||
|  |             src="static/picture/logo1w.png" | |||
|  |             alt="" | |||
|  |           /> | |||
|  |           <div class="nav"> | |||
|  |             <a class="" href="index.html"><span>首页</span></a | |||
|  |             ><a class="active" href=""><span>文本翻译</span></a | |||
|  |             ><a class="" href="voice.html"><span>语音翻译</span></a | |||
|  |             ><a class="" href="api.html"><span>API文档</span></a | |||
|  |             ><a class="" href="commonProblems.html"><span>常见问题</span></a> | |||
|  |           </div> | |||
|  |         </div> | |||
|  |         <div v-if="userInfo!=undefined&&userInfo.userId>0" class="right"> | |||
|  |           <a href="userInfo.html" class="console">控制台</a> | |||
|  |           <div class="user-info"> | |||
|  |             <div class="phone">{{userInfo.name}}</div> | |||
|  |             <i></i> | |||
|  |             <div class="log-out" @click="logOut">退出</div> | |||
|  |           </div> | |||
|  |         </div> | |||
|  |         <div v-else class="right"> | |||
|  |           <a class="unlogin" href="login.html">登录</a> | |||
|  |         </div> | |||
|  |       </div> | |||
|  |       <div class="bg"></div> | |||
|  |     </div> | |||
|  |     <script type="text/javascript"> | |||
|  |       var vm = new Vue({ | |||
|  |         el: "#main", | |||
|  |         data() { | |||
|  |           return { | |||
|  |             userInfo: {}, | |||
|  |             token: "", | |||
|  |           }; | |||
|  |         }, | |||
|  |         created() {}, | |||
|  |         mounted() { | |||
|  |           let token = localStorage.getItem("token"); | |||
|  |           if (token) { | |||
|  |             this.token = token; | |||
|  |             this.getUserInfo(token); | |||
|  |           } else { | |||
|  |             // location.href = "login.html"; | |||
|  |           } | |||
|  |         }, | |||
|  |         methods: { | |||
|  |           logOut() { | |||
|  |             axios | |||
|  |               .post("/logout", { | |||
|  |                 headers: { | |||
|  |                   Authorization: `Bearer ${this.token}`, | |||
|  |                 }, | |||
|  |               }) | |||
|  |               .then((response) => { | |||
|  |                 localStorage.removeItem("token"); | |||
|  |                 location.reload(); | |||
|  |               }); | |||
|  |           }, | |||
|  | 
 | |||
|  |           getUserInfo(token) { | |||
|  |             let that = this; | |||
|  |             axios | |||
|  |               .get("/getinfo", { | |||
|  |                 headers: { | |||
|  |                   Authorization: `Bearer ${this.token}`, | |||
|  |                 }, | |||
|  |               }) | |||
|  |               .then((response) => { | |||
|  |                 if (response.data.code === 200) { | |||
|  |                   this.userInfo = response.data.data; | |||
|  |                   console.log("userinfo", this.userInfo); | |||
|  |                 } else { | |||
|  |                   localStorage.removeItem("token"); | |||
|  |                   location.href = "login.html"; | |||
|  |                 } | |||
|  |               }); | |||
|  |           }, | |||
|  |         }, | |||
|  |       }); | |||
|  |     </script> | |||
|  |     <div class="page-translation" id="app"> | |||
|  |       <div class="w1200"> | |||
|  |         <div class="translation-engine"> | |||
|  |           <div | |||
|  |             v-for="item in engineType" | |||
|  |             :key="item.key" | |||
|  |             class="item" | |||
|  |             :class="{ on: engine.key == item.key }" | |||
|  |             @click="onSelectEngine(item)" | |||
|  |           > | |||
|  |             <img :src="item.icon" alt="" /> | |||
|  |           </div> | |||
|  |         </div> | |||
|  |         <div class="translation-row"> | |||
|  |           <div class="translation-language" @mouseleave="languageShow = false"> | |||
|  |             <div | |||
|  |               class="source" | |||
|  |               @mouseenter="() => onShowLanguage('100px', true, 'sourceLanguage')" | |||
|  |             > | |||
|  |               {{ sourceLanguage.name }} | |||
|  |               <div class="icon select-icon"></div> | |||
|  |             </div> | |||
|  |             <div | |||
|  |               class="target" | |||
|  |               @mouseenter="() => onShowLanguage('620px', true, 'targetLanguage')" | |||
|  |             > | |||
|  |               <div class="icon switch-icon" @click="onSwitch"></div> | |||
|  |               {{ targetLanguage.name }} | |||
|  |               <div class="icon select-icon"></div> | |||
|  |             </div> | |||
|  |             <div | |||
|  |               class="language-row" | |||
|  |               :class="{ show: languageShow }" | |||
|  |               :style="{ left: languageRowLeft }" | |||
|  |             > | |||
|  |               <div class="search"> | |||
|  |                 <i class="icon"></i | |||
|  |                 ><input | |||
|  |                   type="text" | |||
|  |                   class="search-input" | |||
|  |                   v-model="serachKeywords" | |||
|  |                   placeholder="搜索你想要的" | |||
|  |                 /> | |||
|  |               </div> | |||
|  |               <div class="row"> | |||
|  |                 <div | |||
|  |                   v-for="(k, v) in languageCurrent" | |||
|  |                   :key="v" | |||
|  |                   :value="v" | |||
|  |                   class="col" | |||
|  |                   @click="onSelectLanguage(v)" | |||
|  |                   :class="{ on: sourceLanguage.key == v || targetLanguage.key == v }" | |||
|  |                 > | |||
|  |                   <span>{{ k }}</span> | |||
|  |                 </div> | |||
|  |               </div> | |||
|  |             </div> | |||
|  |           </div> | |||
|  |           <div class="translation-text"> | |||
|  |             <div class="source"> | |||
|  |               <textarea | |||
|  |                 cols="30" | |||
|  |                 rows="10" | |||
|  |                 v-model="sourceText" | |||
|  |                 placeholder="输入文字,即可翻译" | |||
|  |               ></textarea> | |||
|  |             </div> | |||
|  |             <div class="target"> | |||
|  |               <textarea | |||
|  |                 disabled | |||
|  |                 cols="30" | |||
|  |                 rows="10" | |||
|  |                 v-model="targetText" | |||
|  |               ></textarea> | |||
|  |               <div class="loading" v-if="isLoading"> | |||
|  |                 <img class="icon" src="static/picture/p17.png" alt="" /> | |||
|  |                 <div>Loading...</div> | |||
|  |               </div> | |||
|  |               <div v-if="targetText" class="copy" @click="copy">复制</div> | |||
|  |             </div> | |||
|  |           </div> | |||
|  |         </div> | |||
|  |       </div> | |||
|  |     </div> | |||
|  |     <script src="static/js/lodash.min.js"></script> | |||
|  |     <script type="text/javascript"> | |||
|  |       const CancelToken = axios.CancelToken; | |||
|  |       let source = CancelToken.source(); | |||
|  |       new Vue({ | |||
|  |         el: "#app", | |||
|  |         data() { | |||
|  |           return { | |||
|  |             engine: {}, | |||
|  |             engineType: [ | |||
|  |               { | |||
|  |                 key: "deepl", | |||
|  |                 value: 0, | |||
|  |                 icon: "https://codeai.oss-cn-hangzhou.aliyuncs.com/img/p2.png", | |||
|  |               }, | |||
|  |               { | |||
|  |                 key: "google", | |||
|  |                 value: 1, | |||
|  |                 icon: "https://codeai.oss-cn-hangzhou.aliyuncs.com/img/p3.png", | |||
|  |               }, | |||
|  |               { | |||
|  |                 key: "baidu", | |||
|  |                 value: 2, | |||
|  |                 icon: "https://codeai.oss-cn-hangzhou.aliyuncs.com/img/p4.png", | |||
|  |               }, | |||
|  |               { | |||
|  |                 key: "youdao", | |||
|  |                 value: 3, | |||
|  |                 icon: "https://codeai.oss-cn-hangzhou.aliyuncs.com/img/youdao.png", | |||
|  |               }, | |||
|  |               { | |||
|  |                 key: "bing", | |||
|  |                 value: 4, | |||
|  |                 icon: "https://codeai.oss-cn-hangzhou.aliyuncs.com/img/bing.png", | |||
|  |               }, | |||
|  |               { | |||
|  |                 key: "huoshan", | |||
|  |                 value: 5, | |||
|  |                 icon: "https://codeai.oss-cn-hangzhou.aliyuncs.com/img/huoshan.png", | |||
|  |               }, | |||
|  |               { | |||
|  |                 key: "chatgpt", | |||
|  |                 value: 6, | |||
|  |                 icon: "https://codeai.oss-cn-hangzhou.aliyuncs.com/img/openai.png", | |||
|  |               }, | |||
|  |               { | |||
|  |                 key: "yandex", | |||
|  |                 value: 7, | |||
|  |                 icon: "https://codeai.oss-cn-hangzhou.aliyuncs.com/img/yandex.png", | |||
|  |               }, | |||
|  |             ], | |||
|  |             sourceLanguage: { | |||
|  |               key: "auto", | |||
|  |               name: "自动检测", | |||
|  |             }, | |||
|  |             targetLanguage: { | |||
|  |               key: "ZH", | |||
|  |               name: "中文(简体)", | |||
|  |             }, | |||
|  |             sourceText: "", | |||
|  |             targetText: "", | |||
|  |             serachKeywords: "", | |||
|  |             languageShow: false, | |||
|  |             languageRowLeft: "100px", | |||
|  |             languageTotalData: {}, | |||
|  |             isLoading: false, | |||
|  |           }; | |||
|  |         }, | |||
|  |         created() { | |||
|  |           this.engine = this.engineType[0]; | |||
|  |           this.getLanguage(); | |||
|  |         }, | |||
|  |         mounted() { | |||
|  |           let token = localStorage.getItem("token"); | |||
|  |           if (token) { | |||
|  |             this.token = token; | |||
|  |             this.getUserInfo(token); | |||
|  |           } else { | |||
|  |             // location.href = "login.html"; | |||
|  |           } | |||
|  |         }, | |||
|  |         watch: { | |||
|  |           sourceText(v) { | |||
|  |             if (v) { | |||
|  |               // _.debounce(this.translate, 500) | |||
|  |               this.translate(); | |||
|  |             } else { | |||
|  |               source.cancel("取消请求"); | |||
|  |               this.targetText = ""; | |||
|  |             } | |||
|  |           }, | |||
|  |         }, | |||
|  |         computed: { | |||
|  |           languageCurrent() { | |||
|  |             const current = this.languageTotalData[this.engine.key]; | |||
|  |             const copyCurrent = {}; | |||
|  |             if (this.serachKeywords) { | |||
|  |               Object.keys(current).forEach((key) => { | |||
|  |                 // console.log('current[key]', current[key]) | |||
|  |                 if (current[key].indexOf(this.serachKeywords) > -1) { | |||
|  |                   copyCurrent[key] = current[key]; | |||
|  |                 } | |||
|  |               }); | |||
|  |               return copyCurrent; | |||
|  |             } | |||
|  |             return this.languageTotalData[this.engine.key]; | |||
|  |           }, | |||
|  |         }, | |||
|  |         methods: { | |||
|  |           copy() { | |||
|  |             // 模拟 输入框 | |||
|  |             var cInput = document.createElement("input"); | |||
|  |             cInput.value = this.targetText; | |||
|  |             document.body.appendChild(cInput); | |||
|  |             cInput.select(); // 选取文本框内容 | |||
|  | 
 | |||
|  |             // 执行浏览器复制命令 | |||
|  |             // 复制命令会将当前选中的内容复制到剪切板中(这里就是创建的input标签) | |||
|  |             // Input要在正常的编辑状态下原生复制方法才会生效 | |||
|  | 
 | |||
|  |             document.execCommand("copy"); | |||
|  |             layer.msg("复制成功"); | |||
|  |             // 复制成功后再将构造的标签 移除 | |||
|  |             document.body.removeChild(cInput); | |||
|  |           }, | |||
|  |           onShowLanguage(left, boolean, key) { | |||
|  |             this.languageRowLeft = left ? left : "100px"; | |||
|  |             this.languageShow = boolean; | |||
|  |             this.currentKey = key; | |||
|  |           }, | |||
|  |           onSelectEngine(e) { | |||
|  |             this.engine = e; | |||
|  |             const firstEntry = Object.entries(this.languageCurrent)[0]; | |||
|  |             this.targetLanguage = { | |||
|  |               key: firstEntry[0], | |||
|  |               name: this.languageCurrent[firstEntry[0]], | |||
|  |             }; | |||
|  |             this.translate(); | |||
|  |           }, | |||
|  |           getLanguage() { | |||
|  |             axios.get("/api/translate/getLanguages").then((res) => { | |||
|  |               if (res.data.code == 1) { | |||
|  |                 this.languageTotalData = res.data.data; | |||
|  |               } | |||
|  |             }); | |||
|  |           }, | |||
|  |           translate: _.debounce(function () { | |||
|  |             source.cancel("取消请求"); | |||
|  |             source = axios.CancelToken.source(); | |||
|  |             const that = this; | |||
|  |             if (!this.sourceText) { | |||
|  |               that.targetText = ""; | |||
|  |               return; | |||
|  |             } | |||
|  |             this.isLoading = true; | |||
|  |             axios | |||
|  |               .post( | |||
|  |                 "/api/translate/index", | |||
|  |                 { | |||
|  |                   keywords: this.sourceText, | |||
|  |                   targetLanguage: this.targetLanguage.key, | |||
|  |                   type: this.engine.value, // 0 :deepl, 1:谷歌 2:百度 | |||
|  |                 }, | |||
|  |                 { cancelToken: source.token } | |||
|  |               ) | |||
|  |               .then(function (res) { | |||
|  |                 console.log(res.data.data.text); | |||
|  |                 if (res.data.code == 1) { | |||
|  |                   that.targetText = res.data.data.text; | |||
|  |                   if (!this.sourceText) { | |||
|  |                     this.targetText = ""; | |||
|  |                   } | |||
|  |                 } else { | |||
|  |                   that.targetText = ""; | |||
|  |                   layer.msg(res.data.info); | |||
|  |                 } | |||
|  |               }) | |||
|  |               .catch(function (err) { | |||
|  |                 console.log(err); | |||
|  |               }) | |||
|  |               .finally(() => { | |||
|  |                 this.isLoading = false; | |||
|  |               }); | |||
|  |           }, 800), | |||
|  |           onSelectLanguage(e) { | |||
|  |             this[this.currentKey] = { | |||
|  |               key: e, | |||
|  |               name: this.languageCurrent[e], | |||
|  |             }; | |||
|  |             this.languageShow = false; | |||
|  |             this.translate(); | |||
|  |           }, | |||
|  |           onSwitch() { | |||
|  |             const copySource = JSON.parse(JSON.stringify(this.sourceLanguage)); | |||
|  |             const copyTarget = JSON.parse(JSON.stringify(this.targetLanguage)); | |||
|  |             this.targetLanguage = copySource; | |||
|  |             this.sourceLanguage = copyTarget; | |||
|  |           }, | |||
|  |           onInput(e) { | |||
|  |             if (this.sourceText) { | |||
|  |               // _.debounce(this.translate, 500) | |||
|  |               this.translate(); | |||
|  |             } else { | |||
|  |               this.targetText = ""; | |||
|  |             } | |||
|  |           }, | |||
|  |         }, | |||
|  |       }); | |||
|  |     </script> | |||
|  |     <div class="public-footer"> | |||
|  |       <div class="w1200"> | |||
|  |         <div class="left"><img src="static/picture/logo.png" alt="" /></div> | |||
|  |         <div | |||
|  |           style=" | |||
|  |             flex-direction: column; | |||
|  |             line-height: 23px; | |||
|  |             padding-left: 100px; | |||
|  |             color: #fff; | |||
|  |             font-size: 12px; | |||
|  |           " | |||
|  |         > | |||
|  |           <p style="color: #fff; font-size: 12px"><span>关于我们:</span></p> | |||
|  |           <p style="color: #fff; font-size: 12px"> | |||
|  |             <span></span> | |||
|  |           </p> | |||
|  |         </div> | |||
|  |         <div class="right" style="white-space: nowrap"> | |||
|  |           <p></p> | |||
|  |           <p><span>联系我们:</span></p> | |||
|  |           <p><span>地址:</span></p> | |||
|  |           <p><span></span></p> | |||
|  |           <p class=""><span>电话: </span></p> | |||
|  |         </div> | |||
|  |       </div> | |||
|  |       <div class="copyright"> | |||
|  |         <a href="https://beian.miit.gov.cn/" target="blank" | |||
|  |           ></a | |||
|  |         > | |||
|  |       </div> | |||
|  |     </div> | |||
|  |   </body> | |||
|  | </html> |