From 8665daa7aa863f96d0d8f27c167edae1efc38022 Mon Sep 17 00:00:00 2001
From: zjk <852185829@qq.com>
Date: 星期五, 31 七月 2026 14:46:19 +0800
Subject: [PATCH] Merge branch 'master' into dev
---
ruoyi-ui/src/views/visitor-admin/system/version.vue | 155 ++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 138 insertions(+), 17 deletions(-)
diff --git a/ruoyi-ui/src/views/visitor-admin/system/version.vue b/ruoyi-ui/src/views/visitor-admin/system/version.vue
index 8c42ae2..4b20bb6 100644
--- a/ruoyi-ui/src/views/visitor-admin/system/version.vue
+++ b/ruoyi-ui/src/views/visitor-admin/system/version.vue
@@ -13,20 +13,28 @@
<th>版本号</th>
<th>更新内容</th>
<th>创建时间</th>
- <th v-if="!isMiddlePlatformReadonly && $auth.hasPermi('visitor:version:remove')">操作</th>
+ <th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in versionList" :key="row.updateId || index">
<td>{{ index + 1 }}</td>
- <td>v{{ row.versionNo }}</td>
+ <td>
+ {{ formatVersionNo(row.versionNo) }}
+ <el-tag v-if="row.latest" size="mini" type="success">最新</el-tag>
+ </td>
<td class="version-content-cell">
<span class="version-content-text">{{ row.updateContent || '-' }}</span>
</td>
<td>{{ parseTime(row.createTime) }}</td>
- <td v-if="!isMiddlePlatformReadonly && $auth.hasPermi('visitor:version:remove')">
+ <td>
<div class="table-actions">
- <button v-hasPermi="['visitor:version:remove']" type="button" @click="handleDelete(row)">删除</button>
+ <button type="button" @click="handleView(row)">查看</button>
+ <button
+ v-if="!row.latest && !isMiddlePlatformReadonly && $auth.hasPermi('visitor:version:remove')"
+ type="button"
+ @click="handleDelete(row)"
+ >删除</button>
</div>
</td>
</tr>
@@ -36,36 +44,70 @@
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
</section>
- <el-dialog title="新建" :visible.sync="open" width="482px" append-to-body>
+ <el-dialog title="版本详情" :visible.sync="detailOpen" width="560px" append-to-body>
+ <el-form label-width="100px">
+ <el-form-item label="版本号">
+ <span>{{ formatVersionNo(detail.versionNo) }}</span>
+ <el-tag v-if="detail.latest" size="mini" type="success">最新</el-tag>
+ </el-form-item>
+ <el-form-item label="更新内容">
+ <div style="white-space: pre-wrap; word-break: break-all;">{{ detail.updateContent || '-' }}</div>
+ </el-form-item>
+ <el-form-item label="安装包">{{ detail.packageName || detail.packageUrl || '-' }}</el-form-item>
+ <el-form-item label="强制更新">{{ detail.forceUpdate ? '是' : '否' }}</el-form-item>
+ <el-form-item label="创建时间">{{ parseTime(detail.createTime) || '-' }}</el-form-item>
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button @click="detailOpen = false">关闭</el-button>
+ </div>
+ </el-dialog>
+
+ <el-dialog title="新建" :visible.sync="open" width="482px" append-to-body custom-class="version-create-dialog">
<form class="version-form" @submit.prevent="submitForm">
<label class="version-row required">
<span>版本号:</span>
<div class="version-input-line">
<span>v</span>
- <input v-model="form.versionNo" class="visitor-native-input" type="text" placeholder="请输入">
+ <input
+ v-model="form.versionNo"
+ class="visitor-native-input"
+ type="text"
+ inputmode="decimal"
+ pattern="[0-9]+(\.[0-9]+)*"
+ placeholder="请输入"
+ @input="handleVersionNoInput"
+ >
</div>
</label>
<label class="version-row">
<span>更新内容</span>
- <textarea v-model="form.updateContent" class="visitor-native-textarea" placeholder="请输入"></textarea>
+ <textarea v-model="form.updateContent" class="visitor-native-textarea" placeholder="请输入" />
</label>
<div class="version-row required">
<span>安装包:</span>
- <div>
- <button class="upload-drop" :class="{ 'has-file': packageFileName }" type="button" @click="$refs.packageFile.click()">
+ <div class="version-upload-field">
+ <button
+ class="upload-drop"
+ :class="{ 'has-file': packageFileName, 'drag-over': packageDragActive }"
+ type="button"
+ @click="$refs.packageFile.click()"
+ @dragover.prevent="handlePackageDragOver"
+ @dragleave="handlePackageDragLeave"
+ @drop.prevent="handlePackageDrop"
+ >
<input ref="packageFile" type="file" hidden @change="handlePackageChange">
<span><strong>{{ packageFileName ? packageFileName : '点击上传' }}</strong><i v-if="!packageFileName"> / </i>{{ packageFileName ? '' : '拖拽到此区域' }}</span>
</button>
- <p class="upload-tip">请上传安装包文件,大小在60M以内</p>
+ <p class="upload-tip">请上传安装包文件,大小须小于200M</p>
</div>
</div>
<label class="version-row switch-line">
<span>强制更新</span>
<input v-model="form.forceUpdate" type="checkbox">
- <span class="switch-control"></span>
+ <span class="switch-control" />
</label>
<footer class="visitor-form-actions">
@@ -78,8 +120,10 @@
</template>
<script>
-import { listVersion, addVersion, delVersion } from '@/api/visitor-admin/version'
-import { getPageRows, getPageTotal } from '@/utils/visitor-admin'
+import { listVersion, getVersion, addVersion, delVersion, uploadVersionPackage } from '@/api/visitor-admin/version'
+import { getPageRows, getPageTotal, getResponseData } from '@/utils/visitor-admin'
+
+const MAX_PACKAGE_SIZE = 200 * 1024 * 1024
export default {
name: 'VisitorVersionUpdate',
@@ -89,7 +133,11 @@
loading: false,
total: 0,
open: false,
+ detailOpen: false,
+ detail: {},
+ packageFile: null,
packageFileName: '',
+ packageDragActive: false,
versionList: [],
queryParams: {
pageNum: 1,
@@ -114,6 +162,11 @@
this.loading = false
})
},
+ // 目的:兼容历史版本号是否包含 v 前缀,统一按 v+版本号展示。
+ formatVersionNo(versionNo) {
+ const value = String(versionNo || '').replace(/^[vV]/, '')
+ return value ? `v${value}` : '-'
+ },
// 目的:打开新增版本弹窗;中台只读模式下禁止本地新增。
handleAdd() {
if (this.isMiddlePlatformReadonly) {
@@ -121,16 +174,59 @@
return
}
this.form = { forceUpdate: false, versionNo: '', updateContent: '', packageName: '', packageUrl: '' }
+ this.packageFile = null
this.packageFileName = ''
+ this.packageDragActive = false
+ if (this.$refs.packageFile) {
+ this.$refs.packageFile.value = ''
+ }
this.open = true
},
- // 目的:记录选择的安装包文件名,并回填版本包名称和地址字段。
+ // 目的:版本号只保留数字和小数点,支持多段版本号输入。
+ handleVersionNoInput(event) {
+ const versionNo = event.target.value.replace(/[^\d.]/g, '').replace(/\.{2,}/g, '.')
+ event.target.value = versionNo
+ this.form.versionNo = versionNo
+ },
+ // 目的:通过文件选择框读取安装包,并复用统一校验逻辑。
handlePackageChange(event) {
const file = event.target.files && event.target.files[0]
+ this.setPackageFile(file, event.target)
+ },
+ // 目的:拖拽文件经过上传区域时阻止浏览器默认行为并展示激活状态。
+ handlePackageDragOver() {
+ this.packageDragActive = true
+ },
+ // 目的:文件离开整个上传区域后恢复默认样式,避免子元素切换导致闪烁。
+ handlePackageDragLeave(event) {
+ if (!event.currentTarget.contains(event.relatedTarget)) {
+ this.packageDragActive = false
+ }
+ },
+ // 目的:接收拖放的首个文件,并复用文件选择框的校验和回填逻辑。
+ handlePackageDrop(event) {
+ this.packageDragActive = false
+ const file = event.dataTransfer.files && event.dataTransfer.files[0]
+ this.setPackageFile(file, this.$refs.packageFile)
+ },
+ // 目的:统一处理点击选择与拖拽选择的安装包,避免重复校验逻辑。
+ setPackageFile(file, input) {
+ if (file && file.size >= MAX_PACKAGE_SIZE) {
+ this.$modal.msgError('操作失败:安装包大小必须小于200M')
+ if (input) {
+ input.value = ''
+ }
+ this.packageFile = null
+ this.packageFileName = ''
+ this.form.packageName = ''
+ this.form.packageUrl = ''
+ return
+ }
+ this.packageFile = file || null
this.packageFileName = file ? file.name : ''
if (file) {
this.form.packageName = file.name
- this.form.packageUrl = file.name
+ this.form.packageUrl = ''
}
},
// 目的:校验并提交新增版本;中台只读模式下禁止提交。
@@ -139,14 +235,35 @@
this.denyMiddlePlatformWrite()
return
}
- if (!this.form.versionNo || !this.form.packageUrl) {
+ if (!/^\d+(\.\d+)*$/.test(this.form.versionNo || '') || !this.packageFile) {
this.$modal.msgError('请填写版本号并上传安装包')
return
}
- addVersion(this.form).then(() => {
+ if (this.packageFile.size >= MAX_PACKAGE_SIZE) {
+ this.$modal.msgError('操作失败:安装包大小必须小于200M')
+ return
+ }
+ const formData = new FormData()
+ formData.append('file', this.packageFile)
+ uploadVersionPackage(formData).then(res => {
+ const data = getResponseData(res) || {}
+ this.form.packageUrl = data.fileName || data.url || ''
+ this.form.packageName = data.originalFilename || data.newFileName || this.packageFile.name
+ if (!this.form.packageUrl) {
+ throw new Error('安装包上传失败,未返回文件地址')
+ }
+ return addVersion(this.form)
+ }).then(() => {
this.$modal.msgSuccess('新增成功')
this.open = false
this.getList()
+ })
+ },
+ // 目的:查看任意版本的完整更新信息。
+ handleView(row) {
+ getVersion(row.updateId).then(res => {
+ this.detail = getResponseData(res) || {}
+ this.detailOpen = true
})
},
// 目的:删除版本更新记录;中台只读模式下禁止本地删除。
@@ -155,6 +272,10 @@
this.denyMiddlePlatformWrite()
return
}
+ if (row.latest) {
+ this.$modal.msgWarning('最新版本不能删除')
+ return
+ }
this.$modal.confirm('是否确认删除该版本记录?').then(() => delVersion([row.updateId])).then(() => {
this.$modal.msgSuccess('删除成功')
this.getList()
--
Gitblit v1.7.1