Compare commits

...

11 Commits

Author SHA1 Message Date
ygxbnet cd061668f9 style(code): 统一代码格式化和导入顺序调整
部署开发环境 / deploy-dev (push) Successful in 2m54s
- 调整了多个组件中的导入语句顺序以保持一致
- 格式化了 App.vue 中的 CSS 样式规则使其更易读
- 规范化了 vite.config.ts 中的配置对象缩进
- 移除了未使用的 computed 导入以减少代码冗余
- 整理了图标组件的导入顺序使其按字母排序
- 统一了代码中的空行和缩进格式
2026-05-01 14:04:26 +08:00
ygxbnet cee1687373 fix(build): 修正版本号链接标志设置
部署开发环境 / deploy-dev (push) Successful in 1m25s
- 修正了 ldflags 中版本变量的包路径,从 global.Version 更新为 dypid/global.Version
- 确保版本信息能够正确注入到二进制文件中
2026-04-30 22:12:40 +08:00
ygxbnet 28aec98414 feat(api): 添加版本信息接口并完善构建流程
部署开发环境 / deploy-dev (push) Successful in 1m22s
- 在api路由中添加/version接口用于显示程序版本信息
- 集成全局Version变量用于版本号管理
- 修改Dockerfile支持版本号注入构建参数
- 更新开发环境部署工作流添加版本信息构建
- 更新生产环境部署工作流添加版本信息构建
- 实现在版本接口中展示程序版本和Gin框架版本
2026-04-30 22:06:21 +08:00
ygxbnet 6d379714cd feat(api): 添加测试接口
部署开发环境 / deploy-dev (push) Successful in 1m35s
- 新增 /test 接口返回 "ok"
- 集成到 API 路由组中
2026-04-30 21:46:25 +08:00
ygxbnet 8c615d01b1 style(home): 移除未使用的CSS注释
部署开发环境 / deploy-dev (push) Successful in 1m41s
- 删除了 search-box 样式中的注释掉的 justify-content 属性
2026-04-25 13:39:45 +08:00
ygxbnet d4eb597575 chore(go): 更新 Go 版本到 1.26
部署开发环境 / deploy-dev (push) Failing after 26s
- 将 go.mod 中的 Go 版本从 1.25 升级到 1.26
- 保持其他依赖项不变
2026-04-25 13:35:10 +08:00
ygxbnet f8022662aa refactor(admin): 移除未使用的Element Plus图标导入
- 从AdminView.vue中移除未使用的Delete、Clock、Document图标导入
- 从TokenManageView.vue中移除未使用的Document、Search、DocumentAdd图标导入
- 优化代码结构,减少不必要的依赖引入
- 修复AddDataDialog组件属性缩进格式问题
2026-04-25 13:23:27 +08:00
ygxbnet 1c7d71e688 feat(home): 主界面添加数据上传功能
- 集成 Upload 图标并导入 AddDataDialog 组件
- 添加显示添加数据对话框的响应式变量
- 新增成功样式按钮用于触发数据上传功能
- 在页面中添加 AddDataDialog 组件实例
- 调整搜索框布局样式以优化界面显示
2026-04-25 13:22:00 +08:00
ygxbnet 462c476141 refactor(AddDataDialog): 移除未使用的 node:timers 导入
部署开发环境 / deploy-dev (push) Successful in 1m27s
- 删除了未被引用的 timers 模块导入
- 清理了组件中无用的依赖引入
2026-04-24 17:51:02 +08:00
ygxbnet 409aac8486 feat(token): 添加数据批量上传功能
部署开发环境 / deploy-dev (push) Failing after 26s
- 新增 AddDataDialog 组件用于数据批量上传
- 在 TokenManageView 中集成数据上传对话框
- 实现按行分割数据并逐条上传的功能
- 添加上传进度显示和计数功能
- 集成 API 接口进行数据提交
- 添加上传状态控制和错误处理机制
2026-04-24 17:48:42 +08:00
ygxbnet 4ca3356214 feat(admin): 添加管理员后台布局并优化Token管理界面
- 新增AdminView.vue作为管理员后台主布局组件
- 集成导航菜单支持Token管理和详情页面切换
- 添加管理员身份标识和退出功能
- 在TokenManageView中引入DocumentAdd图标用于数据添加
- 为表格行添加数据查看对话框功能
- 调整Token管理表格列宽度以改善显示效果
- 优化移动端响应式布局适配
2026-04-24 16:51:20 +08:00
15 changed files with 309 additions and 58 deletions
+5 -1
View File
@@ -11,7 +11,11 @@ jobs:
uses: actions/checkout@v4
- 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: 导出镜像
run: mkdir release && docker save -o release/dypid.tar dypid:latest && docker rmi dypid:latest
+5 -1
View File
@@ -12,7 +12,11 @@ jobs:
uses: actions/checkout@v4
- 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: 导出镜像
run: mkdir release && docker save -o release/dypid.tar dypid:latest && docker rmi dypid:latest
+5 -1
View File
@@ -15,9 +15,13 @@ WORKDIR /build
COPY . .
COPY --from=webBuilder /build/dist ./web/dist
ARG VERSION
RUN go env -w CGO_ENABLED=0 \
&& go mod tidy \
&& go build -o dypid
&& go build \
-ldflags="-s -w -X 'dypid/global.Version=$VERSION'" \
-o dypid
FROM alpine
+10
View File
@@ -1,8 +1,10 @@
package api
import (
"dypid/global"
"dypid/internal/controller"
"embed"
"fmt"
"io/fs"
"net/http"
@@ -11,6 +13,14 @@ import (
func RegRoutes(r *gin.Engine) {
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.POST("/token", controller.CreateTokenHandler) //创建token
+2
View File
@@ -8,3 +8,5 @@ import (
var RDB *redis.Client
var RCtx = context.Background()
var Version = "dev"
+1 -1
View File
@@ -1,6 +1,6 @@
module dypid
go 1.25
go 1.26
require (
github.com/gin-contrib/cors v1.7.6
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

+79 -22
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref } from 'vue'
import {ref} from 'vue'
const themeMode = ref('light')
</script>
@@ -104,30 +104,87 @@ html, body, #app {
}
/* Gap 间距 */
.gap-sm { gap: 8px; }
.gap-md { gap: 12px; }
.gap-lg { gap: 16px; }
.gap-sm {
gap: 8px;
}
.gap-md {
gap: 12px;
}
.gap-lg {
gap: 16px;
}
/* 间距工具类 */
.mt-sm { margin-top: 8px; }
.mt-md { margin-top: 16px; }
.mt-lg { margin-top: 24px; }
.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; }
.mt-sm {
margin-top: 8px;
}
.mt-md {
margin-top: 16px;
}
.mt-lg {
margin-top: 24px;
}
.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-success { color: var(--success-color); }
.text-warning { color: var(--warning-color); }
.text-danger { color: var(--danger-color); }
.text-info { color: var(--info-color); }
.text-primary {
color: var(--text-primary);
}
.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 {
@@ -153,7 +210,7 @@ html, body, #app {
padding: 16px;
border-radius: 0;
}
.hide-on-mobile {
display: none;
}
+149
View File
@@ -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>
添加数据&nbsp;
<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 -1
View File
@@ -1,4 +1,4 @@
import {ref, computed} from 'vue'
import {ref} from 'vue'
import {defineStore} from 'pinia'
export const useCounterStore = defineStore('counter', () => {
+3 -3
View File
@@ -1,8 +1,8 @@
<script setup lang="ts">
import {ref, watch, computed} from 'vue'
import {ref, watch} 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 {CloseBold, Document, Edit, User} 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>
+13 -7
View File
@@ -1,12 +1,10 @@
<script setup lang="ts">
import {ref, onMounted, onUnmounted} from 'vue'
import {onMounted, onUnmounted, ref} from 'vue'
import axios from "@/axios.ts"
import {useRoute} from "vue-router"
import {ElMessage} from "element-plus"
import {
Key, Refresh, Delete, DataAnalysis,
Document, Warning, Search, InfoFilled
} from '@element-plus/icons-vue'
import {DataAnalysis, Document, Key, Search, Upload, Warning} from '@element-plus/icons-vue'
import AddDataDialog from "@/components/AddDataDialog.vue";
const route = useRoute()
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 loading = ref(false)
const lastUpdate = ref('')
const showAddDataDialog = ref(false)
const updateTime = () => {
const now = new Date()
@@ -87,8 +86,16 @@ const statCards = [
<el-button type="primary" size="large" @click="fetchInfo" :loading="loading">
查询
</el-button>
<el-button type="success" size="large" @click="showAddDataDialog = true">
<el-icon>
<Upload/>
</el-icon>
增加数据
</el-button>
</div>
<AddDataDialog v-model="showAddDataDialog" :token="token"/>
<div v-if="result" class="result-section">
<div class="result-header">
<span class="section-title">Token 信息</span>
@@ -148,8 +155,7 @@ const statCards = [
}
.token-input {
flex: 1;
max-width: 600px;
max-width: 400px;
}
.result-section {
+2 -5
View File
@@ -1,12 +1,9 @@
<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 axios from "@/axios.ts"
import {ElMessage, ElMessageBox} from 'element-plus'
import {
Key, Refresh, Delete, DataAnalysis,
Document, Warning, Search, InfoFilled
} from '@element-plus/icons-vue'
import {DataAnalysis, Delete, Document, InfoFilled, Key, Refresh, Search, Warning} from '@element-plus/icons-vue'
const store = useCounterStore()
const result = ref<any>(null)
+24 -6
View File
@@ -1,10 +1,11 @@
<script setup lang="ts">
import {ref, onMounted} from "vue"
import {onMounted, ref} from "vue"
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 {Delete, Edit, Key, Lock, Memo, Plus, View} 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>
+10 -10
View File
@@ -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 vueDevTools from 'vite-plugin-vue-devtools'
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
plugins: [
vue(),
vueDevTools(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
},
},
},
})