2024-10-25 14:53:08 +00:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
<html lang="zh">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
|
<title>习题上传</title>
|
|
|
|
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-plus/dist/index.css">
|
|
|
|
|
|
<style>
|
|
|
|
|
|
body {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
height: 100vh;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
background-color: #f4f4f4;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
max-width: 600px;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
background-color: white;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.upload-area {
|
|
|
|
|
|
border: 1px dashed #ccc;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.upload-area.dragging {
|
|
|
|
|
|
border-color: #409EFF;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-textarea__inner {
|
|
|
|
|
|
min-height: 150px;
|
|
|
|
|
|
resize: vertical;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.image-container {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
img {
|
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 600px) {
|
|
|
|
|
|
.container {
|
|
|
|
|
|
width: 90%;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-26 08:29:21 +00:00
|
|
|
|
#buttons {
|
2024-10-25 14:53:08 +00:00
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<div id="app" class="container">
|
|
|
|
|
|
<h2 style="text-align: center;">上传-习题识别工具</h2>
|
|
|
|
|
|
<p style="text-align: center; color: #999;">请上传习题图片,AI将自动处理并返回结果。</p>
|
|
|
|
|
|
|
|
|
|
|
|
<el-upload
|
|
|
|
|
|
drag
|
|
|
|
|
|
action="/predict"
|
|
|
|
|
|
:on-change="handleChange"
|
|
|
|
|
|
:auto-upload="false"
|
|
|
|
|
|
:show-file-list="false"
|
|
|
|
|
|
:before-upload="beforeUpload"
|
|
|
|
|
|
:accept="'image/*'"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="upload-area" :class="{ dragging: dragging }">
|
|
|
|
|
|
<i class="el-icon-upload" style="font-size: 20px;"></i>
|
|
|
|
|
|
<p>请直接粘贴图片</p>
|
|
|
|
|
|
<p>或将图像拖放到此处</p>
|
|
|
|
|
|
<div class="image-container" v-if="uploadedImageUrl">
|
|
|
|
|
|
<img :src="uploadedImageUrl" alt="Uploaded Image">
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p>点击上传或替换当前图片</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-upload>
|
|
|
|
|
|
|
2024-10-26 08:29:21 +00:00
|
|
|
|
<div id="buttons" style="margin-top: 20px; text-align: right;">
|
|
|
|
|
|
<el-button type="primary" @click="submit">发送</el-button>
|
|
|
|
|
|
<el-button type="danger" @click="clear">清空</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2024-10-25 14:53:08 +00:00
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="result"
|
|
|
|
|
|
type="textarea"
|
2024-10-26 08:29:21 +00:00
|
|
|
|
:rows="4"
|
2024-10-25 14:53:08 +00:00
|
|
|
|
readonly
|
|
|
|
|
|
placeholder="AI生成的文本将显示在这里..."
|
2024-10-26 08:29:21 +00:00
|
|
|
|
:autosize="{ minRows: 4 }"
|
2024-10-25 14:53:08 +00:00
|
|
|
|
></el-input>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/element-plus"></script>
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
const {createApp} = Vue;
|
|
|
|
|
|
const {ElUpload, ElInput, ElButton, ElMessage} = ElementPlus;
|
|
|
|
|
|
|
|
|
|
|
|
const app = createApp({
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
dragging: false,
|
|
|
|
|
|
file: null,
|
|
|
|
|
|
result: '',
|
|
|
|
|
|
uploadedImageUrl: ''
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
handleChange(file, fileList) {
|
|
|
|
|
|
this.file = file.raw;
|
|
|
|
|
|
this.uploadedImageUrl = URL.createObjectURL(file.raw);
|
|
|
|
|
|
},
|
|
|
|
|
|
beforeUpload(file) {
|
|
|
|
|
|
// 文件类型和大小的校验
|
|
|
|
|
|
return true;
|
|
|
|
|
|
},
|
|
|
|
|
|
async submit() {
|
|
|
|
|
|
if (!this.file) {
|
|
|
|
|
|
this.$message.error('请选择文件');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
let formData = new FormData();
|
|
|
|
|
|
formData.append('file', this.file);
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await fetch('/predict', {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
body: formData
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
|
throw new Error('Network response was not ok');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const reader = response.body.getReader();
|
|
|
|
|
|
const decoder = new TextDecoder('utf-8');
|
|
|
|
|
|
this.result = ''; // 清空之前的结果
|
|
|
|
|
|
let receivedLength = 0; // 接收到的字节数
|
|
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
|
const {done, value} = await reader.read();
|
|
|
|
|
|
if (done) {
|
|
|
|
|
|
// 流已完全读取
|
|
|
|
|
|
console.log('Stream complete');
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
const chunk = decoder.decode(value, {stream: true});
|
|
|
|
|
|
this.result += chunk;
|
|
|
|
|
|
receivedLength += value.length;
|
|
|
|
|
|
console.log(`Received ${receivedLength} bytes of data so far`);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
this.$message.error('上传失败: ' + error.message);
|
|
|
|
|
|
console.error('Fetch error:', error);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
clear() {
|
|
|
|
|
|
this.file = null;
|
|
|
|
|
|
this.result = '';
|
|
|
|
|
|
this.uploadedImageUrl = '';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
app.use(ElementPlus); // 使用Element Plus
|
|
|
|
|
|
app.mount('#app');
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|