feat: 版本号按分支轨道分开管理,版本号配置收归管理员
master/develop 共用 release 轨(App_Store 打包构建号自增),feature 分支走
feature 轨(构建号永不自增,始终使用手填值),两条轨道的 App_Ver 各自独立。
- versions 改为 tracks 结构,旧的单轨/单值配置在加载时自动迁移进 release 轨
- 新增 config["branch_track"] 记录分支归属,缺省按分支名推断,可在分支管理页改
- 新增 PUT /api/config/branches/track;分支名含 / 时走请求体而非路径参数
- 修复 DELETE /api/config/branches/{name} 无法删除含 / 的分支(405)
- 版本号接口不再对普通用户开放,打包设置页整页改为管理员可见
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'schemes' }" @click="tab = 'schemes'">Schemes 配置</li>
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'branches' }" @click="tab = 'branches'">分支管理</li>
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'upload' }" @click="tab = 'upload'">上传配置</li>
|
||||
<li :class="{ active: tab === 'build' }" @click="tab = 'build'">打包设置</li>
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'build' }" @click="tab = 'build'">打包设置</li>
|
||||
<li v-if="isAdmin" :class="{ active: tab === 'json' }" @click="tab = 'json'">JSON 编辑</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -151,7 +151,10 @@
|
||||
<!-- 分支管理 -->
|
||||
<div v-if="tab === 'branches'">
|
||||
<h2>分支管理</h2>
|
||||
<p style="color: #666; margin-bottom: 16px; font-size: 14px;">管理可打包的代码分支,打包时从对应分支目录获取源码</p>
|
||||
<p style="color: #666; margin-bottom: 16px; font-size: 14px;">
|
||||
管理可打包的代码分支,打包时从对应分支目录获取源码。
|
||||
版本轨道决定该分支使用哪一套版本号:上架(master/develop 共用,App_Store 打包构建号自增)、自测(feature 用,构建号不自增)。
|
||||
</p>
|
||||
<div style="display: flex; gap: 12px; margin-bottom: 16px;">
|
||||
<input v-model="newBranch" type="text" placeholder="输入分支名称" style="flex: 1; padding: 10px 12px; border: 1px solid #d9d9d9; border-radius: 6px; font-size: 14px;">
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 24px;" @click="addBranch">添加分支</button>
|
||||
@@ -160,18 +163,25 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>分支名称</th>
|
||||
<th>版本轨道</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="b in branches" :key="b">
|
||||
<td><strong>{{ b }}</strong></td>
|
||||
<td>
|
||||
<select :value="branchTrack[b] || 'feature'" style="width: auto; padding: 4px 8px;" @change="setBranchTrack(b, $event.target.value)">
|
||||
<option value="release">上架(master/develop)</option>
|
||||
<option value="feature">自测(feature)</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="action-btns">
|
||||
<button class="action-btn delete" @click="deleteBranch(b)">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="!branches.length">
|
||||
<td colspan="2" style="text-align: center; color: #999;">暂无分支配置</td>
|
||||
<td colspan="3" style="text-align: center; color: #999;">暂无分支配置</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -269,21 +279,36 @@
|
||||
<div v-if="tab === 'build'">
|
||||
<h2>打包设置</h2>
|
||||
<div style="max-width: 500px;">
|
||||
<h4 class="section-title">应用版本号</h4>
|
||||
<h4 class="section-title">上架版本号(master / develop)</h4>
|
||||
<div class="form-group">
|
||||
<label>App_Ver(应用版本)</label>
|
||||
<input type="text" v-model="versions.app_ver" placeholder="2.180.0" @input="onAppVerInput">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">格式:主版本.次版本.修订号</div>
|
||||
<input type="text" v-model="versions.release.app_ver" placeholder="2.180.0" @input="onAppVerInput('release')">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">格式:主版本.次版本.修订号。master 与 develop 共用这一套版本号。</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Build_Ver(构建号)</label>
|
||||
<input type="text" v-model="versions.build_ver" placeholder="2.180.0.0">
|
||||
<input type="text" v-model="versions.release.build_ver" placeholder="2.180.0.0">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">
|
||||
四段数字,前三位须与 App_Ver 一致。修改 App_Ver 会自动切换为该版本号已记录的构建号;
|
||||
每个版本号的构建号独立递增,App_Store 打包时自动 +1。一般无需手动修改。
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px; margin-bottom: 24px;" @click="saveVersions">保存版本号</button>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px; margin-bottom: 24px;" @click="saveVersions('release')">保存上架版本号</button>
|
||||
|
||||
<h4 class="section-title">自测版本号(feature 分支)</h4>
|
||||
<div class="form-group">
|
||||
<label>App_Ver(应用版本)</label>
|
||||
<input type="text" v-model="versions.feature.app_ver" placeholder="2.180.0" @input="onAppVerInput('feature')">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">与上架版本号各自独立,互不影响。</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Build_Ver(构建号)</label>
|
||||
<input type="text" v-model="versions.feature.build_ver" placeholder="2.180.0.0">
|
||||
<div style="font-size: 12px; color: #999; margin-top: 4px;">
|
||||
仅供自测,打包时<strong>不会自动递增</strong>,始终使用这里填写的值(默认 .0)。需要区分时请手动修改。
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary" style="width: auto; padding: 10px 32px; margin-bottom: 24px;" @click="saveVersions('feature')">保存自测版本号</button>
|
||||
|
||||
<template v-if="isAdmin">
|
||||
<h4 class="section-title">打包参数</h4>
|
||||
@@ -613,20 +638,30 @@ const servers = ref({})
|
||||
const branches = ref([])
|
||||
const newBranch = ref('')
|
||||
const buildSettings = ref({})
|
||||
const versions = ref({ app_ver: '', build_ver: '' })
|
||||
const buildMap = ref({})
|
||||
// 两条版本轨道:release(master/develop,上架用)与 feature(自测用),各自独立
|
||||
const versions = ref({
|
||||
release: { app_ver: '', build_ver: '' },
|
||||
feature: { app_ver: '', build_ver: '' },
|
||||
})
|
||||
const buildMap = ref({ release: {}, feature: {} })
|
||||
const branchTrack = ref({})
|
||||
|
||||
const applyVersions = (data) => {
|
||||
buildMap.value = data.build_map || {}
|
||||
versions.value = { app_ver: data.app_ver || '', build_ver: data.build_ver || '' }
|
||||
const tracks = data.tracks || {}
|
||||
for (const track of ['release', 'feature']) {
|
||||
const item = tracks[track] || {}
|
||||
buildMap.value[track] = item.build_map || {}
|
||||
versions.value[track] = { app_ver: item.app_ver || '', build_ver: item.build_ver || '' }
|
||||
}
|
||||
branchTrack.value = data.branch_track || {}
|
||||
}
|
||||
|
||||
// 修改 App_Ver 时,自动把 Build_Ver 切换为该版本号已记录的构建号(新版本号则为 .0)
|
||||
const onAppVerInput = () => {
|
||||
const appVer = (versions.value.app_ver || '').trim()
|
||||
const onAppVerInput = (track) => {
|
||||
const appVer = (versions.value[track].app_ver || '').trim()
|
||||
if (/^\d+\.\d+\.\d+$/.test(appVer)) {
|
||||
const n = Number(buildMap.value[appVer] || 0)
|
||||
versions.value.build_ver = `${appVer}.${n}`
|
||||
const n = Number((buildMap.value[track] || {})[appVer] || 0)
|
||||
versions.value[track].build_ver = `${appVer}.${n}`
|
||||
}
|
||||
}
|
||||
const uploadConfig = ref({ mode: 'oss', oss: {}, webdav: {}, dingtalk: {} })
|
||||
@@ -659,12 +694,9 @@ onMounted(async () => {
|
||||
|
||||
const loadData = async () => {
|
||||
if (!isAdmin.value) {
|
||||
const [appsRes, versionsRes] = await Promise.all([
|
||||
authFetch('/api/config/apps'),
|
||||
authFetch('/api/config/versions'),
|
||||
])
|
||||
// 普通用户只能管理 Apps,版本号等配置均为管理员专属
|
||||
const appsRes = await authFetch('/api/config/apps')
|
||||
if (appsRes.ok) apps.value = await appsRes.json()
|
||||
if (versionsRes.ok) applyVersions(await versionsRes.json())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1111,6 +1143,24 @@ const addBranch = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const setBranchTrack = async (name, track) => {
|
||||
try {
|
||||
const res = await authFetch('/api/config/branches/track', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ branch: name, track }),
|
||||
})
|
||||
if (!res.ok) {
|
||||
const err = await res.json()
|
||||
throw new Error(err.detail || '修改失败')
|
||||
}
|
||||
branchTrack.value = { ...branchTrack.value, [name]: track }
|
||||
} catch (e) {
|
||||
alert('修改失败: ' + e.message)
|
||||
await loadData()
|
||||
}
|
||||
}
|
||||
|
||||
const deleteBranch = async (name) => {
|
||||
if (!confirm(`确定删除分支「${name}」?`)) return
|
||||
try {
|
||||
@@ -1132,21 +1182,25 @@ const saveBuildSettings = async () => {
|
||||
alert('设置已保存')
|
||||
}
|
||||
|
||||
const saveVersions = async () => {
|
||||
const saveVersions = async (track = 'release') => {
|
||||
try {
|
||||
const res = await authFetch('/api/config/versions', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
app_ver: versions.value.app_ver,
|
||||
build_ver: versions.value.build_ver,
|
||||
track,
|
||||
app_ver: versions.value[track].app_ver,
|
||||
build_ver: versions.value[track].build_ver,
|
||||
}),
|
||||
})
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
// 回写该版本号最新的构建号,保持本地 build_map 与服务端一致
|
||||
buildMap.value = { ...buildMap.value, [data.app_ver]: Number((data.build_ver.split('.')[3]) || 0) }
|
||||
versions.value = { app_ver: data.app_ver, build_ver: data.build_ver }
|
||||
buildMap.value[track] = {
|
||||
...(buildMap.value[track] || {}),
|
||||
[data.app_ver]: Number((data.build_ver.split('.')[3]) || 0),
|
||||
}
|
||||
versions.value[track] = { app_ver: data.app_ver, build_ver: data.build_ver }
|
||||
alert('版本号已保存')
|
||||
} else {
|
||||
const err = await res.json()
|
||||
|
||||
Reference in New Issue
Block a user