This commit is contained in:
张成
2025-11-26 12:39:21 +08:00
parent 5d59000960
commit 7858459118
12 changed files with 1785 additions and 2 deletions

View File

@@ -0,0 +1,64 @@
/**
* 版本管理 API 服务
*/
class VersionServer {
/**
* 分页查询版本列表
* @param {Object} param - 查询参数
* @param {Object} param.seachOption - 搜索条件
* @param {Object} param.pageOption - 分页选项
* @returns {Promise}
*/
page(param) {
return window.framework.http.post('/version/list', param)
}
/**
* 获取版本详情
* @param {Object} data - 版本数据包含id
* @returns {Promise}
*/
detail(data) {
return window.framework.http.post('/version/detail', data)
}
/**
* 创建版本
* @param {Object} data - 版本数据
* @returns {Promise}
*/
add(data) {
return window.framework.http.post('/version/create', data)
}
/**
* 更新版本
* @param {Object} data - 版本数据
* @returns {Promise}
*/
update(data) {
return window.framework.http.post('/version/update', data)
}
/**
* 删除版本
* @param {Object} row - 版本数据
* @returns {Promise}
*/
del(row) {
return window.framework.http.post('/version/delete', { id: row.id })
}
/**
* 更新版本状态
* @param {Object} data - 包含id和status
* @returns {Promise}
*/
updateStatus(data) {
return window.framework.http.post('/version/update_status', data)
}
}
export default new VersionServer()

View File

@@ -19,6 +19,7 @@ import TaskStatus from '@/views/task/task_status.vue'
// 系统设置模块
import SystemConfig from '@/views/system/system_config.vue'
import Version from '@/views/system/version.vue'
import JobTypes from '@/views/work/job_types.vue'
// 首页模块
@@ -49,6 +50,7 @@ const componentMap = {
// 系统设置模块
'system/system_config': SystemConfig,
'system/version': Version,
'work/job_types': JobTypes,
'home/index': HomeIndex,
}

View File

@@ -0,0 +1,282 @@
<template>
<div class="content-view">
<div class="table-head-tool">
<Button type="primary" @click="showAddWarp">新增版本</Button>
<Form ref="formInline" :model="gridOption.param.seachOption" inline :label-width="80">
<FormItem :label-width="20" class="flex">
<Select v-model="gridOption.param.seachOption.key" style="width: 120px"
:placeholder="seachTypePlaceholder">
<Option v-for="item in seachTypes" :value="item.key" :key="item.key">{{ item.value }}</Option>
</Select>
<Input class="ml10" v-model="gridOption.param.seachOption.value" style="width: 200px" search
placeholder="请输入关键字" @on-search="query(1)" />
</FormItem>
<FormItem label="平台">
<Select v-model="gridOption.param.seachOption.platform" style="width: 120px" clearable @on-change="query(1)">
<Option value="win32">Windows</Option>
<Option value="darwin">macOS</Option>
<Option value="linux">Linux</Option>
</Select>
</FormItem>
<FormItem label="架构">
<Select v-model="gridOption.param.seachOption.arch" style="width: 120px" clearable @on-change="query(1)">
<Option value="x64">x64</Option>
<Option value="ia32">ia32</Option>
<Option value="arm64">arm64</Option>
</Select>
</FormItem>
<FormItem label="状态">
<Select v-model="gridOption.param.seachOption.status" style="width: 120px" clearable @on-change="query(1)">
<Option :value="1">启用</Option>
<Option :value="0">禁用</Option>
</Select>
</FormItem>
<FormItem>
<Button type="primary" @click="query(1)">查询</Button>
<Button type="default" @click="resetQuery" class="ml10">重置</Button>
</FormItem>
</Form>
</div>
<div class="table-body">
<tables :columns="listColumns" :value="gridOption.data" :pageOption="gridOption.param.pageOption"
@changePage="query"></tables>
</div>
<editModal ref="editModal" :columns="editColumns" :rules="gridOption.rules"></editModal>
</div>
</template>
<script>
import versionServer from '@/api/system/version_server.js'
export default {
data() {
let rules = {}
rules["version"] = [
{ required: true, message: '请填写版本号', trigger: 'blur' },
{ pattern: /^\d+\.\d+\.\d+$/, message: '版本号格式错误,应为 x.y.z 格式', trigger: 'blur' }
]
rules["platform"] = [{ required: true, message: '请选择平台', trigger: 'change' }]
rules["arch"] = [{ required: true, message: '请选择架构', trigger: 'change' }]
rules["download_url"] = [{ required: true, message: '请填写下载地址', trigger: 'blur' }]
rules["file_path"] = [{ required: true, message: '请填写文件路径', trigger: 'blur' }]
return {
seachTypes: [
{ key: 'version', value: '版本号' },
{ key: 'platform', value: '平台' },
{ key: 'arch', value: '架构' }
],
gridOption: {
param: {
seachOption: {
key: 'version',
value: '',
platform: null,
arch: null,
status: null
},
pageOption: {
page: 1,
pageSize: 20
}
},
data: [],
rules: rules
},
listColumns: [
{ title: 'ID', key: 'id', minWidth: 80 },
{ title: '版本号', key: 'version', minWidth: 120 },
{
title: '平台',
key: 'platform',
minWidth: 100,
render: (h, params) => {
const platformMap = {
'win32': { text: 'Windows', color: 'blue' },
'darwin': { text: 'macOS', color: 'green' },
'linux': { text: 'Linux', color: 'orange' }
}
const platform = platformMap[params.row.platform] || { text: params.row.platform, color: 'default' }
return h('Tag', { props: { color: platform.color } }, platform.text)
}
},
{
title: '架构',
key: 'arch',
minWidth: 80,
render: (h, params) => {
return h('Tag', { props: { color: 'cyan' } }, params.row.arch.toUpperCase())
}
},
{
title: '文件大小',
key: 'file_size',
minWidth: 120,
render: (h, params) => {
const size = params.row.file_size || 0
const size_mb = (size / 1024 / 1024).toFixed(2)
return h('span', `${size_mb} MB`)
}
},
{
title: '强制更新',
key: 'force_update',
minWidth: 100,
render: (h, params) => {
return h('Tag', {
props: { color: params.row.force_update === 1 ? 'red' : 'default' }
}, params.row.force_update === 1 ? '是' : '否')
}
},
{
title: '状态',
key: 'status',
minWidth: 100,
render: (h, params) => {
return h('Tag', {
props: { color: params.row.status === 1 ? 'success' : 'default' }
}, params.row.status === 1 ? '启用' : '禁用')
}
},
{ title: '下载地址', key: 'download_url', minWidth: 300 },
{ title: '创建时间', key: 'create_time', minWidth: 150 },
{
title: '操作',
key: 'action',
width: 250,
type: 'template',
render: (h, params) => {
let btns = [
{
title: '编辑',
type: 'primary',
click: () => {
this.showEditWarp(params.row)
},
},
{
title: params.row.status === 1 ? '禁用' : '启用',
type: params.row.status === 1 ? 'warning' : 'success',
click: () => {
this.toggleStatus(params.row)
},
},
{
title: '删除',
type: 'error',
click: () => {
this.delConfirm(params.row)
},
},
]
return window.framework.uiTool.getBtn(h, btns)
},
}
],
editColumns: [
{ title: '版本号', key: 'version', type: 'text', required: true, placeholder: '例如1.0.0' },
{
title: '平台',
key: 'platform',
type: 'select',
required: true,
options: [
{ value: 'win32', label: 'Windows' },
{ value: 'darwin', label: 'macOS' },
{ value: 'linux', label: 'Linux' }
]
},
{
title: '架构',
key: 'arch',
type: 'select',
required: true,
options: [
{ value: 'x64', label: 'x64' },
{ value: 'ia32', label: 'ia32' },
{ value: 'arm64', label: 'arm64' }
]
},
{ title: '下载地址', key: 'download_url', type: 'text', required: true, placeholder: '完整的HTTP/HTTPS URL' },
{ title: '文件路径', key: 'file_path', type: 'text', required: true, placeholder: '服务器文件路径' },
{ title: '文件大小(字节)', key: 'file_size', type: 'number', placeholder: '可选,会自动计算' },
{ title: '文件哈希SHA256', key: 'file_hash', type: 'text', placeholder: '可选,会自动计算' },
{ title: '更新日志', key: 'release_notes', type: 'textarea', placeholder: '版本更新说明' },
{ title: '强制更新', key: 'force_update', type: 'switch' },
{ title: '状态', key: 'status', type: 'switch' }
]
}
},
mounted() {
this.query(1)
},
methods: {
query(page) {
this.gridOption.param.pageOption.page = page
versionServer.page(this.gridOption.param).then(res => {
this.gridOption.data = res.data.rows
this.gridOption.param.pageOption.total = res.data.count
})
},
showAddWarp() {
this.$refs.editModal.showModal()
},
showEditWarp(row) {
this.$refs.editModal.showModal(row)
},
toggleStatus(row) {
const new_status = row.status === 1 ? 0 : 1
const action = new_status === 1 ? '启用' : '禁用'
this.$Modal.confirm({
title: '确认操作',
content: `确定要${action}该版本吗?`,
onOk: async () => {
try {
await versionServer.updateStatus({ id: row.id, status: new_status })
this.$Message.success(`${action}成功!`)
this.query(1)
} catch (error) {
this.$Message.error(`${action}失败:${error.message || '未知错误'}`)
}
}
})
},
delConfirm(row) {
window.framework.uiTool.delConfirm(async () => {
await versionServer.del(row)
this.$Message.success('删除成功!')
this.query(1)
})
},
resetQuery() {
this.gridOption.param.seachOption = {
key: 'version',
value: '',
platform: null,
arch: null,
status: null
}
this.query(1)
}
},
computed: {
seachTypePlaceholder() {
const selected = this.seachTypes.find(item => item.key === this.gridOption.param.seachOption.key)
return selected ? selected.value : '请选择搜索类型'
}
}
}
</script>
<style scoped>
.ml10 {
margin-left: 10px;
}
.flex {
display: flex;
align-items: center;
}
</style>