Compare commits
11 Commits
37fd2c2bac
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| cd061668f9 | |||
| cee1687373 | |||
| 28aec98414 | |||
| 6d379714cd | |||
| 8c615d01b1 | |||
| d4eb597575 | |||
| f8022662aa | |||
| 1c7d71e688 | |||
| 462c476141 | |||
| 409aac8486 | |||
| 4ca3356214 |
@@ -11,7 +11,11 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 构建Docker镜像
|
- name: 构建Docker镜像
|
||||||
run: docker build -t dypid:latest .
|
run: |
|
||||||
|
set -x
|
||||||
|
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
||||||
|
build_date=$(TZ=Asia/Shanghai date +"%Y%m%d%H%M")
|
||||||
|
docker build --build-arg VERSION="dev - $build_date - $git_hash" -t dypid:latest .
|
||||||
|
|
||||||
- name: 导出镜像
|
- name: 导出镜像
|
||||||
run: mkdir release && docker save -o release/dypid.tar dypid:latest && docker rmi dypid:latest
|
run: mkdir release && docker save -o release/dypid.tar dypid:latest && docker rmi dypid:latest
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 构建Docker镜像
|
- name: 构建Docker镜像
|
||||||
run: docker build -t dypid:latest .
|
run: |
|
||||||
|
set -x
|
||||||
|
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
||||||
|
build_date=$(TZ=Asia/Shanghai date +"%Y%m%d%H%M")
|
||||||
|
docker build --build-arg VERSION="release - $build_date - $git_hash" -t dypid:latest .
|
||||||
|
|
||||||
- name: 导出镜像
|
- name: 导出镜像
|
||||||
run: mkdir release && docker save -o release/dypid.tar dypid:latest && docker rmi dypid:latest
|
run: mkdir release && docker save -o release/dypid.tar dypid:latest && docker rmi dypid:latest
|
||||||
|
|||||||
+5
-1
@@ -15,9 +15,13 @@ WORKDIR /build
|
|||||||
COPY . .
|
COPY . .
|
||||||
COPY --from=webBuilder /build/dist ./web/dist
|
COPY --from=webBuilder /build/dist ./web/dist
|
||||||
|
|
||||||
|
ARG VERSION
|
||||||
|
|
||||||
RUN go env -w CGO_ENABLED=0 \
|
RUN go env -w CGO_ENABLED=0 \
|
||||||
&& go mod tidy \
|
&& go mod tidy \
|
||||||
&& go build -o dypid
|
&& go build \
|
||||||
|
-ldflags="-s -w -X 'dypid/global.Version=$VERSION'" \
|
||||||
|
-o dypid
|
||||||
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
|
|
||||||
|
|||||||
+10
@@ -1,8 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"dypid/global"
|
||||||
"dypid/internal/controller"
|
"dypid/internal/controller"
|
||||||
"embed"
|
"embed"
|
||||||
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@@ -11,6 +13,14 @@ import (
|
|||||||
|
|
||||||
func RegRoutes(r *gin.Engine) {
|
func RegRoutes(r *gin.Engine) {
|
||||||
g := r.Group("/api") //初始化路由组 /api/xxxx
|
g := r.Group("/api") //初始化路由组 /api/xxxx
|
||||||
|
{
|
||||||
|
g.GET("/test", func(context *gin.Context) {
|
||||||
|
context.String(http.StatusOK, "ok")
|
||||||
|
})
|
||||||
|
g.GET("/version", func(context *gin.Context) {
|
||||||
|
context.String(http.StatusOK, fmt.Sprintf("程序版本: %s\nGin: %s", global.Version, gin.Version))
|
||||||
|
})
|
||||||
|
}
|
||||||
{
|
{
|
||||||
g.GET("/token", controller.ListTokenHandler) //获取token列表
|
g.GET("/token", controller.ListTokenHandler) //获取token列表
|
||||||
g.POST("/token", controller.CreateTokenHandler) //创建token
|
g.POST("/token", controller.CreateTokenHandler) //创建token
|
||||||
|
|||||||
@@ -8,3 +8,5 @@ import (
|
|||||||
|
|
||||||
var RDB *redis.Client
|
var RDB *redis.Client
|
||||||
var RCtx = context.Background()
|
var RCtx = context.Background()
|
||||||
|
|
||||||
|
var Version = "dev"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module dypid
|
module dypid
|
||||||
|
|
||||||
go 1.25
|
go 1.26
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-contrib/cors v1.7.6
|
github.com/gin-contrib/cors v1.7.6
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB |
+79
-22
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import {ref} from 'vue'
|
||||||
|
|
||||||
const themeMode = ref('light')
|
const themeMode = ref('light')
|
||||||
</script>
|
</script>
|
||||||
@@ -104,30 +104,87 @@ html, body, #app {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Gap 间距 */
|
/* Gap 间距 */
|
||||||
.gap-sm { gap: 8px; }
|
.gap-sm {
|
||||||
.gap-md { gap: 12px; }
|
gap: 8px;
|
||||||
.gap-lg { gap: 16px; }
|
}
|
||||||
|
|
||||||
|
.gap-md {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-lg {
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
/* 间距工具类 */
|
/* 间距工具类 */
|
||||||
.mt-sm { margin-top: 8px; }
|
.mt-sm {
|
||||||
.mt-md { margin-top: 16px; }
|
margin-top: 8px;
|
||||||
.mt-lg { margin-top: 24px; }
|
}
|
||||||
.mb-sm { margin-bottom: 8px; }
|
|
||||||
.mb-md { margin-bottom: 16px; }
|
.mt-md {
|
||||||
.mb-lg { margin-bottom: 24px; }
|
margin-top: 16px;
|
||||||
.ml-sm { margin-left: 8px; }
|
}
|
||||||
.ml-md { margin-left: 12px; }
|
|
||||||
.ml-lg { margin-left: 16px; }
|
.mt-lg {
|
||||||
.mr-sm { margin-right: 8px; }
|
margin-top: 24px;
|
||||||
.mr-md { margin-right: 12px; }
|
}
|
||||||
.mr-lg { margin-right: 16px; }
|
|
||||||
|
.mb-sm {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-md {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-lg {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-sm {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-md {
|
||||||
|
margin-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-lg {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-sm {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-md {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mr-lg {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
/* 文本工具类 */
|
/* 文本工具类 */
|
||||||
.text-primary { color: var(--text-primary); }
|
.text-primary {
|
||||||
.text-success { color: var(--success-color); }
|
color: var(--text-primary);
|
||||||
.text-warning { color: var(--warning-color); }
|
}
|
||||||
.text-danger { color: var(--danger-color); }
|
|
||||||
.text-info { color: var(--info-color); }
|
.text-success {
|
||||||
|
color: var(--success-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-warning {
|
||||||
|
color: var(--warning-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-danger {
|
||||||
|
color: var(--danger-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-info {
|
||||||
|
color: var(--info-color);
|
||||||
|
}
|
||||||
|
|
||||||
/* 加载动画 */
|
/* 加载动画 */
|
||||||
.loading-container {
|
.loading-container {
|
||||||
@@ -153,7 +210,7 @@ html, body, #app {
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide-on-mobile {
|
.hide-on-mobile {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {computed, ref} from "vue"
|
||||||
|
import axios from "@/axios.ts"
|
||||||
|
import {ElMessage} from 'element-plus'
|
||||||
|
import {Upload} from '@element-plus/icons-vue'
|
||||||
|
|
||||||
|
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>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import {ref, computed} from 'vue'
|
import {ref} from 'vue'
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
|
|
||||||
export const useCounterStore = defineStore('counter', () => {
|
export const useCounterStore = defineStore('counter', () => {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, watch, computed} from 'vue'
|
import {ref, watch} from 'vue'
|
||||||
import {useRoute, useRouter} from "vue-router"
|
import {useRoute, useRouter} from "vue-router"
|
||||||
import {useCounterStore} from "@/stores/counter.ts"
|
import {useCounterStore} from "@/stores/counter.ts"
|
||||||
import {Edit, Delete, Clock, User, Document} from '@element-plus/icons-vue'
|
import {CloseBold, Document, Edit, User} from '@element-plus/icons-vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -70,7 +70,7 @@ const logout = () => {
|
|||||||
@click="logout"
|
@click="logout"
|
||||||
>
|
>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Delete/>
|
<CloseBold/>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
退出
|
退出
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, onMounted, onUnmounted} from 'vue'
|
import {onMounted, onUnmounted, ref} from 'vue'
|
||||||
import axios from "@/axios.ts"
|
import axios from "@/axios.ts"
|
||||||
import {useRoute} from "vue-router"
|
import {useRoute} from "vue-router"
|
||||||
import {ElMessage} from "element-plus"
|
import {ElMessage} from "element-plus"
|
||||||
import {
|
import {DataAnalysis, Document, Key, Search, Upload, Warning} from '@element-plus/icons-vue'
|
||||||
Key, Refresh, Delete, DataAnalysis,
|
import AddDataDialog from "@/components/AddDataDialog.vue";
|
||||||
Document, Warning, Search, InfoFilled
|
|
||||||
} from '@element-plus/icons-vue'
|
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const token = ref(route.query.token as string || '')
|
const token = ref(route.query.token as string || '')
|
||||||
@@ -14,6 +12,7 @@ const input = ref(route.query.token as string || '')
|
|||||||
const result = ref<any>(null)
|
const result = ref<any>(null)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const lastUpdate = ref('')
|
const lastUpdate = ref('')
|
||||||
|
const showAddDataDialog = ref(false)
|
||||||
|
|
||||||
const updateTime = () => {
|
const updateTime = () => {
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
@@ -87,8 +86,16 @@ const statCards = [
|
|||||||
<el-button type="primary" size="large" @click="fetchInfo" :loading="loading">
|
<el-button type="primary" size="large" @click="fetchInfo" :loading="loading">
|
||||||
查询
|
查询
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button type="success" size="large" @click="showAddDataDialog = true">
|
||||||
|
<el-icon>
|
||||||
|
<Upload/>
|
||||||
|
</el-icon>
|
||||||
|
增加数据
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<AddDataDialog v-model="showAddDataDialog" :token="token"/>
|
||||||
|
|
||||||
<div v-if="result" class="result-section">
|
<div v-if="result" class="result-section">
|
||||||
<div class="result-header">
|
<div class="result-header">
|
||||||
<span class="section-title">Token 信息</span>
|
<span class="section-title">Token 信息</span>
|
||||||
@@ -148,8 +155,7 @@ const statCards = [
|
|||||||
}
|
}
|
||||||
|
|
||||||
.token-input {
|
.token-input {
|
||||||
flex: 1;
|
max-width: 400px;
|
||||||
max-width: 600px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-section {
|
.result-section {
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, onMounted, onUnmounted, watch} from 'vue'
|
import {onMounted, onUnmounted, ref, watch} from 'vue'
|
||||||
import {useCounterStore} from "@/stores/counter.ts"
|
import {useCounterStore} from "@/stores/counter.ts"
|
||||||
import axios from "@/axios.ts"
|
import axios from "@/axios.ts"
|
||||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||||
import {
|
import {DataAnalysis, Delete, Document, InfoFilled, Key, Refresh, Search, Warning} from '@element-plus/icons-vue'
|
||||||
Key, Refresh, Delete, DataAnalysis,
|
|
||||||
Document, Warning, Search, InfoFilled
|
|
||||||
} from '@element-plus/icons-vue'
|
|
||||||
|
|
||||||
const store = useCounterStore()
|
const store = useCounterStore()
|
||||||
const result = ref<any>(null)
|
const result = ref<any>(null)
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, onMounted} from "vue"
|
import {onMounted, ref} from "vue"
|
||||||
import axios from "@/axios.ts"
|
import axios from "@/axios.ts"
|
||||||
import {ElMessage} from 'element-plus'
|
import {ElMessage} from 'element-plus'
|
||||||
import {useCounterStore} from "@/stores/counter.ts"
|
import {useCounterStore} from "@/stores/counter.ts"
|
||||||
import {useRouter} from "vue-router"
|
import {useRouter} from "vue-router"
|
||||||
import {Plus, View, Edit, Delete, Key, Document, Memo, Search, Lock} from '@element-plus/icons-vue'
|
import {Delete, Edit, Key, Lock, Memo, Plus, View} from '@element-plus/icons-vue'
|
||||||
|
import AddDataDialog from '@/components/AddDataDialog.vue'
|
||||||
|
|
||||||
const store = useCounterStore()
|
const store = useCounterStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -19,6 +20,7 @@ const inputPassWord = ref('')
|
|||||||
const passwordVisible = ref(true)
|
const passwordVisible = ref(true)
|
||||||
|
|
||||||
const rowOut = ref<any>(null)
|
const rowOut = ref<any>(null)
|
||||||
|
const addDataDialogVisible = ref(false)
|
||||||
const dedupObjectVisible = ref(false)
|
const dedupObjectVisible = ref(false)
|
||||||
const dataFormatVisible = ref(false)
|
const dataFormatVisible = ref(false)
|
||||||
const inputNotesVisible = ref(false)
|
const inputNotesVisible = ref(false)
|
||||||
@@ -114,6 +116,11 @@ const dialogNotesVisible = (row: any) => {
|
|||||||
inputNotesVisible.value = true
|
inputNotesVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dialogDataADDVisible = (row: any) => {
|
||||||
|
rowOut.value = row
|
||||||
|
addDataDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
const updateDedupObject = async () => {
|
const updateDedupObject = async () => {
|
||||||
try {
|
try {
|
||||||
await axios.put('/api/token', {}, {
|
await axios.put('/api/token', {}, {
|
||||||
@@ -265,7 +272,7 @@ const deleteToken = async (row: any) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table :data="tableData" v-loading="loading" stripe style="width: 100%">
|
<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 }">
|
<template #default="{ row }">
|
||||||
<div class="token-cell">
|
<div class="token-cell">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@@ -282,19 +289,19 @@ const deleteToken = async (row: any) => {
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</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 }">
|
<template #default="{ row }">
|
||||||
<div class="format-cell">{{ row.data_format }}</div>
|
<div class="format-cell">{{ row.data_format }}</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</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 }">
|
<template #default="{ row }">
|
||||||
<span class="notes-text">{{ row.notes || '-' }}</span>
|
<span class="notes-text">{{ row.notes || '-' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="操作" width="280" fixed="right">
|
<el-table-column label="操作" width="500" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
<el-button type="primary" size="small" text @click="viewDetails(row)">
|
<el-button type="primary" size="small" text @click="viewDetails(row)">
|
||||||
@@ -303,6 +310,12 @@ const deleteToken = async (row: any) => {
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
详情
|
详情
|
||||||
</el-button>
|
</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-button size="small" text @click="dialogDedupObjectVisible(row)">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Edit/>
|
<Edit/>
|
||||||
@@ -371,6 +384,11 @@ const deleteToken = async (row: any) => {
|
|||||||
<el-button type="primary" @click="updateNotes">确定</el-button>
|
<el-button type="primary" @click="updateNotes">确定</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<AddDataDialog
|
||||||
|
v-model="addDataDialogVisible"
|
||||||
|
:token="rowOut?.token"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+10
-10
@@ -1,18 +1,18 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import {fileURLToPath, URL} from 'node:url'
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
import {defineConfig} from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
vueDevTools(),
|
vueDevTools(),
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user