Compare commits
2 Commits
37fd2c2bac
...
409aac8486
| Author | SHA1 | Date | |
|---|---|---|---|
| 409aac8486 | |||
| 4ca3356214 |
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,150 @@
|
||||
<script setup lang="ts">
|
||||
import {ref, computed} from "vue"
|
||||
import axios from "@/axios.ts"
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {Upload} from '@element-plus/icons-vue'
|
||||
import * as timers from "node:timers";
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
token?: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: boolean): void
|
||||
}>()
|
||||
|
||||
const inputData = ref('')
|
||||
const uploading = ref(false)
|
||||
const uploadedCount = ref(0)
|
||||
const totalCount = computed(() => {
|
||||
const lines = inputData.value.split('\n').filter(line => line.trim())
|
||||
return lines.length
|
||||
})
|
||||
|
||||
const close = () => {
|
||||
emit('update:modelValue', false)
|
||||
inputData.value = ''
|
||||
uploadedCount.value = 0
|
||||
}
|
||||
|
||||
const handleUpload = async () => {
|
||||
if (!inputData.value.trim()) {
|
||||
ElMessage.warning('请输入数据')
|
||||
return
|
||||
}
|
||||
|
||||
uploading.value = true
|
||||
uploadedCount.value = 0
|
||||
|
||||
const lines = inputData.value.split('\n').filter(line => line.trim())
|
||||
const total = lines.length
|
||||
uploadedCount.value = 0
|
||||
|
||||
for (const line of lines) {
|
||||
try {
|
||||
await axios.post('/api/data', {}, {
|
||||
params: {
|
||||
data: line,
|
||||
token: props.token || ''
|
||||
}
|
||||
})
|
||||
uploadedCount.value++
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error.response?.data?.error || '上传失败')
|
||||
uploading.value = false
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
uploading.value = false
|
||||
ElMessage({message: '已上传成功 ' + uploadedCount.value + ' 条数据', type: 'success'})
|
||||
setTimeout(() => {
|
||||
close()
|
||||
}, 2000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="modelValue"
|
||||
@update:model-value="emit('update:modelValue', $event)"
|
||||
width="700px"
|
||||
:close-on-click-modal="false"
|
||||
@close="close"
|
||||
>
|
||||
<template #title>
|
||||
添加数据
|
||||
<el-tag type="primary" effect="plain">{{ props.token }}</el-tag>
|
||||
</template>
|
||||
<div class="add-data-dialog">
|
||||
<el-input
|
||||
v-model="inputData"
|
||||
type="textarea"
|
||||
:rows="18"
|
||||
placeholder="请输入数据,每行一条"
|
||||
:disabled="uploading"
|
||||
class="textarea-input"
|
||||
/>
|
||||
|
||||
<div class="footer">
|
||||
<div class="progress">
|
||||
<el-progress
|
||||
:percentage="totalCount > 0 ? Math.round((uploadedCount / totalCount) * 100) : 0"
|
||||
:show-text="false"
|
||||
/>
|
||||
<span class="progress-text">已上传 {{ uploadedCount }}/{{ totalCount }} 行</span>
|
||||
</div>
|
||||
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="uploading"
|
||||
@click="handleUpload"
|
||||
>
|
||||
<el-icon v-if="!uploading">
|
||||
<Upload/>
|
||||
</el-icon>
|
||||
上传
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.add-data-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.textarea-input :deep(.el-textarea__inner) {
|
||||
overflow-x: auto;
|
||||
white-space: pre;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.footer .el-progress {
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -2,7 +2,7 @@
|
||||
import {ref, watch, computed} from 'vue'
|
||||
import {useRoute, useRouter} from "vue-router"
|
||||
import {useCounterStore} from "@/stores/counter.ts"
|
||||
import {Edit, Delete, Clock, User, Document} from '@element-plus/icons-vue'
|
||||
import {Edit, Delete, Clock, User, Document, CloseBold} from '@element-plus/icons-vue'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
@@ -70,7 +70,7 @@ const logout = () => {
|
||||
@click="logout"
|
||||
>
|
||||
<el-icon>
|
||||
<Delete/>
|
||||
<CloseBold/>
|
||||
</el-icon>
|
||||
退出
|
||||
</el-button>
|
||||
|
||||
@@ -4,7 +4,8 @@ import axios from "@/axios.ts"
|
||||
import {ElMessage} from 'element-plus'
|
||||
import {useCounterStore} from "@/stores/counter.ts"
|
||||
import {useRouter} from "vue-router"
|
||||
import {Plus, View, Edit, Delete, Key, Document, Memo, Search, Lock} from '@element-plus/icons-vue'
|
||||
import {Plus, View, Edit, Delete, Key, Document, Memo, Search, Lock, DocumentAdd} from '@element-plus/icons-vue'
|
||||
import AddDataDialog from '@/components/AddDataDialog.vue'
|
||||
|
||||
const store = useCounterStore()
|
||||
const router = useRouter()
|
||||
@@ -19,6 +20,7 @@ const inputPassWord = ref('')
|
||||
const passwordVisible = ref(true)
|
||||
|
||||
const rowOut = ref<any>(null)
|
||||
const addDataDialogVisible = ref(false)
|
||||
const dedupObjectVisible = ref(false)
|
||||
const dataFormatVisible = ref(false)
|
||||
const inputNotesVisible = ref(false)
|
||||
@@ -114,6 +116,11 @@ const dialogNotesVisible = (row: any) => {
|
||||
inputNotesVisible.value = true
|
||||
}
|
||||
|
||||
const dialogDataADDVisible = (row: any) => {
|
||||
rowOut.value = row
|
||||
addDataDialogVisible.value = true
|
||||
}
|
||||
|
||||
const updateDedupObject = async () => {
|
||||
try {
|
||||
await axios.put('/api/token', {}, {
|
||||
@@ -265,7 +272,7 @@ const deleteToken = async (row: any) => {
|
||||
</div>
|
||||
|
||||
<el-table :data="tableData" v-loading="loading" stripe style="width: 100%">
|
||||
<el-table-column prop="token" label="Token" min-width="200" show-overflow-tooltip>
|
||||
<el-table-column prop="token" label="Token" min-width="100" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<div class="token-cell">
|
||||
<el-icon>
|
||||
@@ -282,19 +289,19 @@ const deleteToken = async (row: any) => {
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="data_format" label="数据格式" min-width="350" show-overflow-tooltip>
|
||||
<el-table-column prop="data_format" label="数据格式" min-width="200" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<div class="format-cell">{{ row.data_format }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="notes" label="备注" min-width="250" show-overflow-tooltip>
|
||||
<el-table-column prop="notes" label="备注" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<span class="notes-text">{{ row.notes || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="280" fixed="right">
|
||||
<el-table-column label="操作" width="500" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="action-buttons">
|
||||
<el-button type="primary" size="small" text @click="viewDetails(row)">
|
||||
@@ -303,6 +310,12 @@ const deleteToken = async (row: any) => {
|
||||
</el-icon>
|
||||
详情
|
||||
</el-button>
|
||||
<el-button size="small" text @click="dialogDataADDVisible(row)">
|
||||
<el-icon>
|
||||
<Plus/>
|
||||
</el-icon>
|
||||
数据
|
||||
</el-button>
|
||||
<el-button size="small" text @click="dialogDedupObjectVisible(row)">
|
||||
<el-icon>
|
||||
<Edit/>
|
||||
@@ -371,6 +384,11 @@ const deleteToken = async (row: any) => {
|
||||
<el-button type="primary" @click="updateNotes">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<AddDataDialog
|
||||
v-model="addDataDialogVisible"
|
||||
:token="rowOut?.token"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user