You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1001 lines
24 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="wrap">
<el-radio-group fill="#022950" v-model="radio1" @change="changeTranslate">
<el-radio-button :label="1" size="large" @click="reset" border>翻译文本</el-radio-button>
<el-radio-button :label="2" size="large" @click="reset" border>翻译文件</el-radio-button>
<el-radio-button :label="3" size="large" @click="reset" border>优化翻译</el-radio-button>
<el-radio-button :label="4" size="large" @click="reset" border>OCR识别</el-radio-button>
</el-radio-group>
<div class="change-wrap">
<el-select v-model="value" class="m-2" popper-class="popper" @click="selectClick1"
placeholder="请选择语言" size="large">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<img src="../assets/images/zhuanhuan.png" alt="">
<el-select v-model="value2" class="m-2" popper-class="popper" @click="selectClick2"
placeholder="请选择语言" size="large">
<el-option
v-for="item in options2"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<el-button v-if="radio1==1||radio1==3" @click="translate">翻译</el-button>
<el-button v-if="radio1==2" @click="translate2">识别</el-button>
<el-button v-if="radio1==4" @click="translate3">识别</el-button>
<div class="select_wrap" v-if="currentLangModalStatus" ref="tanchuang1">
<el-input placeholder="搜索语言" v-model="searchLanguage"
@input="inputChange"></el-input>
<div class="hr"></div>
<div class="language_wrap">
<el-scrollbar class="scrollbar">
<div class="language_box" v-for="(value,key,index) in language" :key="index">
<div class="firstWord">{{ key }}</div>
<span class="language" v-for="(item2,index) in value" @click="selectLanguage(item2)"
:key="index">{{ item2.name }}</span>
</div>
</el-scrollbar>
</div>
</div>
<div class="select_wrap" v-if="targetLangModalStatus" ref="tanchuang2">
<el-input placeholder="搜索语言" v-model="searchLanguage2"
@input="inputChange2"></el-input>
<div class="hr"></div>
<div class="language_wrap">
<el-scrollbar class="scrollbar">
<div class="language_box" v-for="(value,key,index) in language2" :key="index">
<div class="firstWord">{{ key }}</div>
<span class="language" v-for="(item2,index) in value" @click="selectLanguage2(item2)"
:key="index">{{ item2.name }}</span>
</div>
</el-scrollbar>
</div>
</div>
</div>
<div class="import-wrap">
<div class="importBox1">
<span class="importTitle" v-if="radio1==1||radio1==3">{{ value || '检测源语言' }}</span>
<span class="importTitle" v-if="radio1==2||radio1==4">见识别文件</span>
<el-input
v-if="radio1==1||radio1==3"
v-model="textarea"
@input="importIdentifyLanguage"
:rows="2"
type="textarea"
placeholder="输入翻译"/>
<el-upload
v-if="radio1==2"
ref="upload"
class="upload-demo"
drag
limit="1"
:before-upload="beforeUpload"
:on-change="uploadChange"
:on-success="uploadSuccess"
:on-error="uploadError"
accept=".doc,.docx,.xls,.xlsx,.txt,.pdf"
:action="uploadApi"
>
<div class="fileIcon">
<div class="fileIconItem">
<img src="../assets/images/fileIcon2.png" alt="">
<span class="fileIcon_text">pdf</span>
</div>
<!-- <div class="fileIconItem">
<img style="width:55px;height:45px;marginLeft:45px" src="../assets/images/fileIcon2.png" alt="">
<span>jpg/jpeg/png/bmp</span>
</div> -->
<div class="fileIconItem">
<img src="../assets/images/fileIcon3.png" alt="">
<span class="fileIcon_text">txt</span>
</div>
<div class="fileIconItem">
<img src="../assets/images/fileIcon4.png" alt="">
<span class="fileIcon_text">xls/xlsx</span>
</div>
<div class="fileIconItem">
<img src="../assets/images/fileIcon5.png" alt="">
<span class="fileIcon_text">doc/docx</span>
</div>
</div>
<div class="el-upload__text">
点击文件上传
</div>
<div class="el-upload__text2">
支持扩展名doc、docx、xls、xlsx、txt、pdf格式
</div>
</el-upload>
<el-upload
v-if="radio1==4"
ref="upload"
class="upload-demo"
drag
limit="1"
:before-upload="beforeUpload2"
:on-change="uploadChange"
:on-success="uploadSuccess"
:on-error="uploadError"
accept=".pdf,.jpg,.jpeg,.png,.bmp"
:action="uploadApi"
>
<div class="fileIcon">
<div class="fileIconItem">
<img src="../assets/images/fileIcon2.png" alt="">
<span class="fileIcon_text">pdf</span>
</div>
<div class="fileIconItem">
<img src="../assets/images/fileIcon.png" alt="">
<span class="fileIcon_text">jpg/jpeg/png/bmp</span>
</div>
<!-- <div class="fileIconItem">
<img style="width:55px;height:45px;marginLeft:45px" src="../assets/images/fileIcon3.png" alt="">
<span>txt</span>
</div>
<div class="fileIconItem">
<img style="width:55px;height:45px;marginLeft:45px" src="../assets/images/fileIcon4.png" alt="">
<span>xls/xlsx</span>
</div>
<div class="fileIconItem">
<img style="width:55px;height:45px;marginLeft:45px" src="../assets/images/fileIcon5.png" alt="">
<span>doc/docx</span>
</div> -->
</div>
<div class="el-upload__text">
点击文件上传
</div>
<div class="el-upload__text2">
支持扩展名pdf、jpg、jpeg、png、bmp格式
</div>
</el-upload>
</div>
<!-- <div class="importBox3" v-if="radio1==2||radio1==3">
<el-button class="button1">英语</el-button>
<el-button class="button2" @click="translate2">翻译</el-button>
</div> -->
<div class="importBox2">
<span class="importTitle">{{ value2 || '英语(美式)' }}</span>
<!-- <el-input
v-model="textarea2"
:rows="2"
type="textarea"/> -->
<HtmlPreview class="HtmlPreview" :content="textarea2"/>
</div>
</div>
<div class="jilu-wrap">
<div class="jilu"><img src="../assets/images/jilu.png" alt="">翻译记录</div>
<div class="first" v-if="radio1==1" @click="goYouHua">优化翻译</div>
</div>
<div :class="`${prefixCls}-content dynamicInfo flex flex-col `">
<el-form size="large" inline>
<el-row>
<el-col :span="9">
<el-form-item label="选择日期">
<el-date-picker type="daterange" v-model="searchData.selecttime"
placeholder="请选择日期"/>
</el-form-item>
</el-col>
<el-col :span="9">
<el-form-item label="名称">
<el-input v-model="searchData.name" placeholder="请输入关键字"/>
</el-form-item>
</el-col>
<el-col :span="6" :offset="0" class="flex justify-end">
<el-form-item style="margin-right: 0;">
<el-button type="primary" @click="getList(currentTab)">查询</el-button>
<el-button @click="resetData">重置</el-button>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table v-loading="loading" size="large" :data="content" :empty-text="'暂无数据'"
:header-cell-style="{background: '#f5f5f5', color:'#333333'}">
<el-table-column show-overflow-tooltip align="center" label="时间" prop="date"></el-table-column>
<el-table-column show-overflow-tooltip align="center" label="名称" prop="name">
<template #header>
<span>名称</span>
</template>
</el-table-column>
<el-table-column show-overflow-tooltip align="center" label="附件" prop=""></el-table-column>
<el-table-column show-overflow-tooltip align="center" label="操作" prop="notification_time_text">
<template #default="scope">
<span style="color:#E60B0B"><a :href="`${downloadApi}?id=${scope.row.id}`">下载</a></span>
</template>
</el-table-column>
</el-table>
<div class="mt-32">
<Pagination
:current="current"
:limit="limit"
:pages="pagesRef"
:total="total"
@change="onChangePage"
/>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import dayjs from "dayjs";
import {onClickOutside} from "@vueuse/core"
definePageMeta({
name: '翻译',
hidden: true,
hiddenBanner: true,
middleware: ['auth']
})
useHead({
title: '翻译',
script: [
{
type: 'text/javascript',
src: 'https://cdn.bootcss.com/socket.io/1.3.7/socket.io.js'
}
]
})
const uploadApi = computed(()=> import.meta.env.VITE_UPLOAD_API)
const downloadApi = computed(()=> import.meta.env.VITE_DOWNLOAD_API)
const {prefixCls} = useDesign('mai-wrap');
const router = useRouter()
const route = useRoute()
const {translateApi} = useApi()
const searchLanguage = ref('')
const searchLanguage2 = ref('')
const textarea = ref('')
const textarea2 = ref('')
const currentLangModalStatus = ref(false)
const targetLangModalStatus = ref(false)
// const textarea2 = ref('')
const radio1 = ref(route.query?.type ?? 1)
const {setTotal, current, total, setCurrentPage, limit, pagesRef} = usePagination(1, 6, 0)
const currentTab = ref({});
let language = ref({})
let language2 = ref({})
const options = reactive([
{value: 'zh', lable: '中文(简体)'},
{value: "en", lable: '英文'},
])
const options2 = reactive([
{value: 'zh', lable: '中文(简体)'},
{value: "en", lable: '英文'},
])
const value2 = ref('中文')
const value = ref('')
const abbreviation1 = ref('')
const abbreviation2 = ref('zh')
const searchData = ref({
selecttime: '',
name: ''
})
const loading = ref(true);
const content = ref([]);
const tanchuang1 = ref()
const tanchuang2 = ref()
const upload = ref()
const fileUrl = ref('')
const uid = ref('')
const timer2 = ref(1)
const timer3 = ref(1)
const timer4 = ref(1)
const socket = ref(null)
watch(currentLangModalStatus, (val) => {
allLanguage()
})
watch(targetLangModalStatus, (val) => {
allLanguage()
})
watchEffect(() => {
radio1.value = route.query?.type ?? 1;
const user = useUserInfo()
if (user.$state.info.id) {
// window.io = null
// if (process.client) {
// const socketio = document.createElement('script')
// socketio.src = 'https://cdn.bootcss.com/socket.io/1.3.7/socket.io.js'
// document.body.append(socketio)
let timer = setInterval(() => {
// @ts-ignore
if (io) {
// @ts-ignore
socket.value = io('http://research.mcnetmart.com:2120');//这里请填写你的域名外网端口为socket端口
// @ts-ignore
socket.value.on('connect', function () {
// @ts-ingore
console.log('dengll', user)
//@ts-ignore
this.emit('login', user.$state.info.id);
});
console.log('socket>>>>', socket)
clearInterval(timer)
}
}, 1000)
}
})
async function inputChange() {
clearTimeout(timer3.value)
timer3.value = setTimeout(async()=>{
const {data: data} = await translateApi.getAllLanguage({keyword: searchLanguage.value})
language.value = data
},1000)
}
async function inputChange2() {
clearTimeout(timer4.value)
timer4.value = setTimeout(async()=>{
const {data: data} = await translateApi.getAllLanguage({keyword: searchLanguage2.value})
language2.value = data
},1000)
}
function changeTranslate(val: any) {
router.replace({
path: route.path,
query: {
type: val
}
})
}
// function downLoad(index:any,record:any){
// translateApi.downLoad({id:record.id}).then((res)=>{
// console.log(res)
// })
// .catch((error)=>{
// console.log(error)
// })
// }
function beforeUpload(file: any) {
// 截取上传的文件名后缀
let fileExtName = file.name.substring(file.name.lastIndexOf('.') + 1);
console.log(typeof fileExtName)
if(
fileExtName === 'docx' ||
fileExtName === 'doc' ||
fileExtName === 'xls' ||
fileExtName === 'xlsx' ||
fileExtName === 'txt' ||
fileExtName === 'pdf'
){
//进行上传成功的一些操作;
if(value.value){
console.log('file',file);
return true
}else{
ElMessage.success('您还未选择语言')
return false
}
}else{
// 提醒只能上传的文件类型
ElMessage.warning('只能上传.docx,.xls,.xlsx,.txt,.pdf类型的文件');
return false;
}
}
function beforeUpload2(file: any) {
// 截取上传的文件名后缀
let fileExtName = file.name.substring(file.name.lastIndexOf('.') + 1);
if(
fileExtName === 'pdf' ||
fileExtName === 'jpg' ||
fileExtName === 'jpeg' ||
fileExtName === 'png' ||
fileExtName === 'bmp'
){
//进行上传成功的一些操作;
if(value.value){
console.log('file',file);
return true
}else{
ElMessage.success('您还未选择语言')
return false
}
}else{
// 提醒只能上传的文件类型
ElMessage.warning('只能上传.pdf,.jpg,.jpeg,.png,.bmp类型的文件');
return false;
}
}
function uploadChange() {
}
function uploadSuccess(response: any) {
ElMessage.success(response.msg)
console.log(typeof response.data.url)
fileUrl.value = response.data.url
}
function uploadError(response: any) {
ElMessage.error(response.msg)
}
function resetData(flag: boolean = true) {
searchData.value = {
selecttime: '',
name: ''
}
flag && getList(currentTab.value)
}
function goYouHua() {
radio1.value = 3
}
async function importIdentifyLanguage() {
clearTimeout(timer2.value)
timer2.value = setTimeout(async()=>{
if(textarea.value){
const data = await translateApi.identifyLanguage({
content: textarea.value,
})
if(data.code == 1){
value.value = data.data.name
abbreviation1.value = data.data.abbreviation
}else{
value.value = ''
abbreviation1.value = ''
}
}
},500)
}
function reset() {
value.value = ''
value2.value = '中文'
abbreviation1.value = ''
abbreviation2.value = 'zh'
textarea.value = ''
textarea2.value = ''
}
function onChangePage(val: number) {
setCurrentPage(val)
getList(currentTab.value)
}
function selectClick1() {
// debugger
currentLangModalStatus.value = !currentLangModalStatus.value
}
function selectClick2() {
targetLangModalStatus.value = !targetLangModalStatus.value
}
function selectLanguage(item: any) {
console.log(item)
if (currentLangModalStatus.value) {
value.value = item.name
abbreviation1.value = item.abbreviation
currentLangModalStatus.value = false
}
}
function selectLanguage2(item: any) {
console.log(item)
if (targetLangModalStatus.value) {
value2.value = item.name
abbreviation2.value = item.abbreviation
targetLangModalStatus.value = false
}
}
async function translate() {
if (radio1.value == 1) {
const {data: data} = await translateApi.translateText({
content: textarea.value,
source: abbreviation1.value,
target: abbreviation2.value
})
textarea2.value = data
}
if (radio1.value == 3) {
const {data: data} = await translateApi.translateOptimizeText({
content: textarea.value,
source: abbreviation1.value,
target: abbreviation2.value
})
textarea2.value = data
}
}
async function translate3() {
if(value.value&&value2.value&&abbreviation1.value&&abbreviation2.value){
const {data: data} = await translateApi.ocrTranslate({
file: fileUrl.value,
source: abbreviation1.value,
target: abbreviation2.value
})
textarea2.value = data
}else{
ElMessage.success('您还未选择语言,或语言为选全')
}
}
async function translate2() {
if(value.value&&value2.value&&abbreviation1.value&&abbreviation2.value){
translateApi.translateFile({
file: fileUrl.value,
source: abbreviation1.value,
target: abbreviation2.value
}).then(res => {
// @ts-ignore
socket.value.on('translateDoc', async (msg) => {
console.log("收到消息:" + msg);
// 调接口
translateApi.getUserTranslateDocInfo({id: msg}).then((data) => {
textarea2.value = data.data.after_content
})
});
})
}else{
ElMessage.success('您还未选择语言,或语言为选全')
}
}
async function allLanguage() {
const {data: data} = await translateApi.getAllLanguage({})
language.value = data
language2.value = data
}
async function getList(data: any) {
if (data) {
loading.value = true;
const searchParams = {
...searchData.value,
start_date: '',
end_date: '',
type: 0
}
if (searchData.value.selecttime) {
searchParams.start_date = dayjs(searchData.value.selecttime[1]).format('YYYY-DD-MM hh:mm:ss')
searchParams.end_date = dayjs(searchData.value.selecttime[0]).format('YYYY-DD-MM hh:mm:ss')
// @ts-ignore
delete searchParams.selecttime;
}
searchParams.type = radio1.value as number
const {data: listDatas} = await translateApi.getTranslateList({
...searchParams,
page: current.value,
limit: limit,
category_id: data.id
})
content.value = listDatas.data;
loading.value = false;
setTotal(listDatas.total)
}
}
onClickOutside(tanchuang1, () => {
currentLangModalStatus.value = false
})
onClickOutside(tanchuang2, () => {
targetLangModalStatus.value = false
})
getList(currentTab.value)
allLanguage()
</script>
<style lang="scss">
.popper {
display: none !important;
}
</style>
<style lang="scss" scoped>
* {
--el-color-primary: #022950
}
.wrap {
padding: 0 244px 50px 244px;
background-color: #EEF1F9;
}
.el-radio-group {
margin-top: 42px;
margin-bottom: 76px;
}
.el-radio-button {
border-radius: 16px;
margin-right: 12px;
border: 0px;
outline: none;
width: 218px;
height: 61px;
}
:deep(.el-radio-button__inner) {
width: 218px;
height: 61px;
border: 0px;
outline: none;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: 400;
color: #333333;
border-radius: 16px !important;
}
:deep(.el-input__wrapper) {
width: 218px;
height: 61px;
background: #FFFFFF;
border-radius: 16px;
border-color: #ffffff;
}
:deep(.el-input__inner) {
//text-align: center;
}
.change-wrap {
display: flex;
align-items: center;
margin-bottom: 24px;
position: relative;
:deep(.el-input__wrapper) {
font-size: 20px !important;
}
.el-button {
width: 218px;
height: 61px;
background: #022950;
border-radius: 16px;
color: #FFFFFF;
font-size: 20px;
margin-left: 24px;
}
img {
width: 55px;
height: 44px;
margin: 0 28px 0 34px;
}
}
:deep(.el-textarea__inner) {
width: 100%;
height: 239px;
border-radius: 16px;
border: 0px;
padding-top: 17px;
padding-left: 37px;
}
.el-textarea {
border-radius: 16px;
margin-top: 17px;
font-size: 36px;
}
.import-wrap {
display: flex;
justify-content: center;
// align-items: center;
.importBox1 {
flex: 1;
margin-right: 32px;
}
.importBox3 {
flex: 0.25;
margin-right: 22px;
.el-button {
width: 150px;
height: 55px;
margin: 0;
border-radius: 8px;
font-size: 20px;
}
.button1 {
margin-bottom: 24px;
color: #BABABA;
background-color: #fff;
}
.button2 {
color: #fff;
background-color: #022950;
}
}
.importBox2 {
flex: 1;
}
}
.importTitle {
width: 120px;
height: 28px;
font-size: 20px;
font-weight: 400;
color: #333333;
line-height: 28px;
margin-left: 10px;
}
.el-select {
margin: 0;
}
.jilu-wrap {
display: flex;
justify-content: space-between;
font-size: 20px;
margin-top: 30px;
.jilu {
display: flex;
justify-content: center;
align-items: center;
width: 158px;
height: 49px;
background: #E8EBF5;
border-radius: 16px;
color: #333333;
img {
width: 20px;
height: 20px;
margin-right: 12px;
}
}
.first {
color: #E60B0B;
cursor: pointer;
}
}
.yangliu-mai-wrap-content {
margin: 30px 0 0 0;
width: 100%;
}
// .dynamicInfo {
// margin-top: 0;
// padding-bottom: 100px;
// }
:deep(.el-table__inner-wrapper) {
font-size: 20px;
}
:deep(.el-table__header-wrapper) {
height: 80px;
}
:deep(.el-table__header) {
height: 80px;
}
:deep(.el-table__empty-block) {
height: 300px !important;
}
:deep(.el-form) {
margin-bottom: 43px;
.el-form-item__label {
height: 60px;
line-height: 60px !important;
padding-right: 16px;
@apply text-xl;
}
.el-input__wrapper {
border-radius: 10px;
height: 60px;
width: 448px;
box-shadow: unset;
background-color: #ffffff;
@apply text-xl;
}
.el-icon {
font-size: 20px;
}
.el-range-input {
font-size: 20px;
}
.el-button {
width: 150px;
height: 60px;
box-shadow: unset;
@apply text-xl rounded-xl;
&--primary {
background-color: #022950;
}
}
}
:deep(.el-upload) {
margin-top: 17px;
border-radius: 16px;
}
:deep(.el-upload-dragger) {
height: 239px;
border-radius: 16px;
}
:deep(.el-upload) {
height: 239px;
border-radius: 16px;
}
.el-upload__text {
font-size: 16px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #333333;
line-height: 22px;
margin-bottom: 30px;
display: flex;
justify-content: center;
align-items: center;
}
.el-upload__text2 {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
display: flex;
justify-content: center;
align-items: center;
}
:deep(.el-table__cell) {
padding: 26px 0 !important;
}
.select_wrap {
width: 100%;
// width: 1436px;
padding-left: 32px;
padding-right: 40px;
height: 774px;
background: #FFFFFF;
box-shadow: 0px 0px 22px 7px rgba(224, 224, 224, 0.5);
border-radius: 16px;
position: absolute;
top: 65px;
left: 0;
z-index: 100;
:deep(.el-input__inner) {
text-align: left;
font-size: 24px;
font-weight: 400;
color: #CACACA;
}
.hr {
width: 100%;
height: 1px;
background: #D8D8D8;
}
.scrollbar {
:deep(.el-scrollbar__bar) {
width: 13px !important;
border-radius: 6.5px !important;
}
}
.language_wrap {
height: 698px;
overflow-y: auto;
padding-bottom: 64px;
.language_box {
padding: 0 5px;
.firstWord {
font-size: 18px;
font-weight: 400;
color: #999999;
margin-top: 24px;
}
.language {
font-size: 20px;
font-weight: 400;
color: #333333;
margin-top: 20px;
display: inline-block;
margin-right: 24px;
cursor: pointer;
}
}
}
}
:deep(.el-input__wrapper) {
border: none !important;
box-shadow: none !important;
// padding: 0px; //前边边距去掉
}
.HtmlPreview {
height: 239px !important;
margin: 17px;
border-radius: 16px;
background-color: #fff;
}
.mt-32{
height: 140px;
display: flex;
justify-content: center;
align-items: center;
padding-top: 40px;
background-color: #fff;
margin: 0;
}
.fileIcon{
display: flex;
// justify-content: center;
align-items: center;
margin-top: -10px;
margin-bottom: 15px;
.fileIconItem{
margin-left: 45px;
img{
width: 64px;
height: 64px;
}
}
.fileIcon_text{
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 17px;
}
.fileIcon_text2{
margin-top: -10px;
}
}
</style>