feat(tenant-platform): editable changelog with audit trail in version table
Adds an edit button (pencil icon) on each row's changelog cell.
Clicking it opens a dialog pre-filled with the current text; saving
calls PATCH /app/{id}/changelog and refreshes the list and op-log.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
7d100a9efc
当前提交
416783047c
@ -236,6 +236,10 @@ export const updateAdminApi = {
|
|||||||
return updateClient.post(`/api/v1/updates/app/${id}/unpublish`, { reason })
|
return updateClient.post(`/api/v1/updates/app/${id}/unpublish`, { reason })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
patchChangeLog(id: string, changeLog: string) {
|
||||||
|
return updateClient.patch<{ data: AppVersion }>(`/api/v1/updates/app/${id}/changelog`, { changeLog })
|
||||||
|
},
|
||||||
|
|
||||||
grayAppVersion(id: string, body: {
|
grayAppVersion(id: string, body: {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
grayMode: GrayMode
|
grayMode: GrayMode
|
||||||
|
|||||||
@ -106,7 +106,16 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="changeLog" label="更新说明" show-overflow-tooltip />
|
<el-table-column label="更新说明" min-width="160">
|
||||||
|
<template #default="{row}">
|
||||||
|
<el-tooltip :content="row.changeLog || '(无)'" placement="top" :disabled="!row.changeLog">
|
||||||
|
<span class="changelog-text">{{ row.changeLog || '—' }}</span>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-button link type="primary" size="small" style="margin-left:4px" @click="openChangelogEdit(row)">
|
||||||
|
<el-icon><Edit /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="createdAt" label="上传时间" width="160">
|
<el-table-column prop="createdAt" label="上传时间" width="160">
|
||||||
<template #default="{row}">{{ formatTime(row.createdAt) }}</template>
|
<template #default="{row}">{{ formatTime(row.createdAt) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -670,6 +679,22 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- Changelog Edit Dialog -->
|
||||||
|
<el-dialog v-model="showChangelogEdit" title="修改更新说明" width="480px">
|
||||||
|
<el-input
|
||||||
|
v-model="changelogEditValue"
|
||||||
|
type="textarea"
|
||||||
|
:rows="5"
|
||||||
|
placeholder="请输入更新说明(可留空)"
|
||||||
|
maxlength="2000"
|
||||||
|
show-word-limit
|
||||||
|
/>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="showChangelogEdit = false">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="savingChangelog" @click="submitChangelogEdit">保存</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<!-- Store Credential Config Dialog -->
|
<!-- Store Credential Config Dialog -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="showStoreConfig"
|
v-model="showStoreConfig"
|
||||||
@ -880,7 +905,7 @@
|
|||||||
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { CircleCheckFilled, Loading, UploadFilled, WarningFilled } from '@element-plus/icons-vue'
|
import { CircleCheckFilled, Edit, Loading, UploadFilled, WarningFilled } from '@element-plus/icons-vue'
|
||||||
import { appApi, type App } from '@/api/app'
|
import { appApi, type App } from '@/api/app'
|
||||||
import { fileApi } from '@/api/file'
|
import { fileApi } from '@/api/file'
|
||||||
import {
|
import {
|
||||||
@ -1471,6 +1496,32 @@ const publishScheduleType = ref<'IMMEDIATE' | 'SCHEDULED'>('IMMEDIATE')
|
|||||||
const publishScheduleAt = ref('')
|
const publishScheduleAt = ref('')
|
||||||
const updatingPublishSchedule = ref(false)
|
const updatingPublishSchedule = ref(false)
|
||||||
|
|
||||||
|
const showChangelogEdit = ref(false)
|
||||||
|
const changelogEditId = ref('')
|
||||||
|
const changelogEditValue = ref('')
|
||||||
|
const savingChangelog = ref(false)
|
||||||
|
|
||||||
|
function openChangelogEdit(row: AppVersion) {
|
||||||
|
changelogEditId.value = row.id
|
||||||
|
changelogEditValue.value = row.changeLog ?? ''
|
||||||
|
showChangelogEdit.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitChangelogEdit() {
|
||||||
|
savingChangelog.value = true
|
||||||
|
try {
|
||||||
|
await updateAdminApi.patchChangeLog(changelogEditId.value, changelogEditValue.value)
|
||||||
|
ElMessage.success('更新说明已保存')
|
||||||
|
showChangelogEdit.value = false
|
||||||
|
await loadAppVersions()
|
||||||
|
await loadOperationLogs()
|
||||||
|
} catch {
|
||||||
|
ElMessage.error('保存失败')
|
||||||
|
} finally {
|
||||||
|
savingChangelog.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleCancelReview(storeType?: string) {
|
async function handleCancelReview(storeType?: string) {
|
||||||
if (!storeReviewDetailVersion.value) return
|
if (!storeReviewDetailVersion.value) return
|
||||||
const stores = storeType
|
const stores = storeType
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户