<template>
|
<main class="version-page">
|
<section class="version-card">
|
<header class="version-header">
|
<h1>访客机版本更新</h1>
|
<button v-if="!isMiddlePlatformReadonly" v-hasPermi="['visitor:version:add']" class="add-button" type="button" @click="handleAdd">+ 新建</button>
|
</header>
|
|
<table class="version-table">
|
<thead>
|
<tr>
|
<th>序号</th>
|
<th>版本号</th>
|
<th>更新内容</th>
|
<th>创建时间</th>
|
<th>操作</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr v-for="(row, index) in versionList" :key="row.updateId || index">
|
<td>{{ index + 1 }}</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>
|
<div class="table-actions">
|
<button type="button" @click="handleView(row)">查看</button>
|
<button
|
v-if="!isMiddlePlatformReadonly && $auth.hasPermi('visitor:version:edit')"
|
type="button"
|
@click="handleEdit(row)"
|
>编辑</button>
|
<button
|
v-if="!row.latest && !isMiddlePlatformReadonly && $auth.hasPermi('visitor:version:remove')"
|
type="button"
|
@click="handleDelete(row)"
|
>删除</button>
|
</div>
|
</td>
|
</tr>
|
</tbody>
|
</table>
|
<div v-if="!loading && !versionList.length" class="visitor-empty">暂无版本更新数据</div>
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
|
</section>
|
|
<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="form.updateId ? '编辑' : '新建'" :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"
|
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="请输入" />
|
</label>
|
|
<div class="version-row required">
|
<span>安装包:</span>
|
<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">{{ form.updateId ? '不重新上传将保留原安装包,文件大小须小于200M' : '请上传安装包文件,大小须小于200M' }}</p>
|
</div>
|
</div>
|
|
<label class="version-row switch-line">
|
<span>强制更新</span>
|
<input v-model="form.forceUpdate" type="checkbox">
|
<span class="switch-control" />
|
</label>
|
|
<footer class="visitor-form-actions">
|
<button class="ghost-button" type="button" @click="open = false">取消</button>
|
<button class="primary-button" type="submit">确定</button>
|
</footer>
|
</form>
|
</el-dialog>
|
</main>
|
</template>
|
|
<script>
|
import { listVersion, getVersion, addVersion, editVersion, delVersion, uploadVersionPackage } from '@/api/visitor-admin/version'
|
import { getPageRows, getPageTotal, getResponseData, normalizeBoolean } from '@/utils/visitor-admin'
|
|
const MAX_PACKAGE_SIZE = 200 * 1024 * 1024
|
|
export default {
|
name: 'VisitorVersionUpdate',
|
// 目的:初始化版本列表查询状态、弹窗状态和版本表单数据。
|
data() {
|
return {
|
loading: false,
|
total: 0,
|
open: false,
|
detailOpen: false,
|
detail: {},
|
packageFile: null,
|
packageFileName: '',
|
packageDragActive: false,
|
versionList: [],
|
queryParams: {
|
pageNum: 1,
|
pageSize: 10,
|
versionNo: ''
|
},
|
form: {}
|
}
|
},
|
// 目的:页面创建时加载版本更新记录。
|
created() {
|
this.getList()
|
},
|
methods: {
|
// 目的:按当前查询条件加载版本更新分页列表。
|
getList() {
|
this.loading = true
|
listVersion(this.queryParams).then(res => {
|
this.versionList = getPageRows(res)
|
this.total = getPageTotal(res)
|
}).finally(() => {
|
this.loading = false
|
})
|
},
|
// 目的:兼容历史版本号是否包含 v 前缀,统一按 v+版本号展示。
|
formatVersionNo(versionNo) {
|
const value = String(versionNo || '').replace(/^[vV]/, '')
|
return value ? `v${value}` : '-'
|
},
|
// 目的:打开新增版本弹窗;非本地维护页面的中台只读模式下禁止本地新增。
|
handleAdd() {
|
if (this.isMiddlePlatformReadonly) {
|
this.denyMiddlePlatformWrite()
|
return
|
}
|
this.form = { updateId: null, 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
|
},
|
// 目的:读取完整版本信息后进入编辑态,未选择新文件时保留原安装包。
|
handleEdit(row) {
|
if (this.isMiddlePlatformReadonly) {
|
this.denyMiddlePlatformWrite()
|
return
|
}
|
getVersion(row.updateId).then(res => {
|
const data = getResponseData(res) || {}
|
this.form = {
|
updateId: data.updateId,
|
versionNo: String(data.versionNo || '').replace(/^[vV]/, ''),
|
updateContent: data.updateContent || '',
|
packageUrl: data.packageUrl || '',
|
packageName: data.packageName || '',
|
forceUpdate: normalizeBoolean(data.forceUpdate)
|
}
|
this.packageFile = null
|
this.packageFileName = data.packageName || data.packageUrl || ''
|
this.packageDragActive = false
|
this.open = true
|
this.$nextTick(() => {
|
if (this.$refs.packageFile) {
|
this.$refs.packageFile.value = ''
|
}
|
})
|
})
|
},
|
// 目的:版本号只保留数字和小数点,支持多段版本号输入。
|
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.updateId ? (this.form.packageName || this.form.packageUrl || '') : ''
|
return
|
}
|
this.packageFile = file || null
|
this.packageFileName = file ? file.name : ''
|
},
|
// 目的:统一校验并提交新增或编辑版本,编辑时仅在重新选择文件后上传安装包。
|
submitForm() {
|
if (this.isMiddlePlatformReadonly) {
|
this.denyMiddlePlatformWrite()
|
return
|
}
|
const isEdit = Boolean(this.form.updateId)
|
if (!/^\d+(\.\d+)*$/.test(this.form.versionNo || '') || (!this.packageFile && !this.form.packageUrl)) {
|
this.$modal.msgError('请填写版本号并上传安装包')
|
return
|
}
|
if (this.packageFile && this.packageFile.size >= MAX_PACKAGE_SIZE) {
|
this.$modal.msgError('操作失败:安装包大小必须小于200M')
|
return
|
}
|
const uploadRequest = this.packageFile ? this.uploadPackage() : Promise.resolve()
|
uploadRequest.then(() => isEdit ? editVersion(this.form) : addVersion(this.form)).then(() => {
|
this.$modal.msgSuccess(isEdit ? '编辑成功' : '新增成功')
|
this.open = false
|
this.getList()
|
})
|
},
|
// 目的:上传当前选择的安装包,并把服务端文件信息回填到版本表单。
|
uploadPackage() {
|
const packageFile = this.packageFile
|
const formData = new FormData()
|
formData.append('file', packageFile)
|
return uploadVersionPackage(formData).then(res => {
|
const data = getResponseData(res) || {}
|
this.form.packageUrl = data.fileName || data.url || ''
|
this.form.packageName = data.originalFilename || data.newFileName || packageFile.name
|
if (!this.form.packageUrl) {
|
throw new Error('安装包上传失败,未返回文件地址')
|
}
|
})
|
},
|
// 目的:查看任意版本的完整更新信息。
|
handleView(row) {
|
getVersion(row.updateId).then(res => {
|
this.detail = getResponseData(res) || {}
|
this.detailOpen = true
|
})
|
},
|
// 目的:删除版本更新记录;中台只读模式下禁止本地删除。
|
handleDelete(row) {
|
if (this.isMiddlePlatformReadonly) {
|
this.denyMiddlePlatformWrite()
|
return
|
}
|
if (row.latest) {
|
this.$modal.msgWarning('最新版本不能删除')
|
return
|
}
|
this.$modal.confirm('是否确认删除该版本记录?').then(() => delVersion([row.updateId])).then(() => {
|
this.$modal.msgSuccess('删除成功')
|
this.getList()
|
})
|
}
|
}
|
}
|
</script>
|