Files
cms-SiteForge/integrations/art-design-pro/src/views/siteforge/ReleaseCenter.vue
T
浅念 601451f22b upgrade: adopt V8.21.3 (V8.13→8.21.3: P5 SFTP/S3, P6 multilingual, editor overhaul, enterprise hardening)
Overlay ~150 upstream items onto our V8.12 base, preserving trade-pro
theme, registry tests, and design docs. Re-applied our patch set
(discovery/env_for/blocks.css/type-mapping/theme_color/frontend entries,
test_theme_pro_v3 mods) — all anchors survived upstream evolution.

New platform enhancement (fixes upgrade-introduced regression):
multilingual.site_locale now honors settings_json.locale, plus
PUT /api/i18n/sites/{id}/locale — standalone English sites get
<html lang='en'> under the V8.15 locale-rewrite pipeline.

compose: adopt V8.21.3 (image 8.21.3-dev.1, /api/ready probes, MySQL/S3
env) with project name pinned to siteforge-v8-10 (data volumes).

Tests: 356 passed / 11 failed — all 11 confirmed pre-existing in
pristine V8.21.3 on this host (10 upstream Windows env + our build test
now green after locale fix). Patch registry updated in plan doc.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-23 12:31:03 +08:00

21 lines
3.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template><section class="release-center"><h2>构建与发布中心</h2><p>构建先通过迁移与质量验收,再提交独立审批;通过后才能部署到预先配置的 HTTPS 环境。</p>
<el-card shadow="never"><el-space><el-select v-model="siteId" @change="reload" style="width:240px"><el-option v-for="s in sites" :label="s.name" :value="s.id" :key="s.id" /></el-select><el-button @click="reload" :loading="loading">刷新任务</el-button></el-space></el-card>
<el-card shadow="never" style="margin-top:16px"><template #header>构建版本</template><el-table :data="builds" max-height="360"><el-table-column prop="id" label="版本ID" min-width="170"/><el-table-column prop="status" label="状态" width="110"/><el-table-column prop="total_pages" label="页面数" width="90"/><el-table-column prop="created_at" label="生成日期" width="180"/><el-table-column label="操作" min-width="260"><template #default="{row}"><el-button link @click="review(row.id)">申请审批</el-button><el-button link type="primary" @click="deploy(row.id,'staging')">发布测试环境</el-button><el-button link type="danger" @click="deploy(row.id,'production')">正式发布</el-button></template></el-table-column></el-table></el-card>
<el-card shadow="never" style="margin-top:16px"><template #header>审批请求</template><el-table :data="requests"><el-table-column prop="build_id" label="构建ID"/><el-table-column prop="state" label="审批状态" width="150"/><el-table-column prop="requested_by" label="申请人"/><el-table-column label="操作"><template #default="{row}"><el-button v-if="row.state==='pending'" link @click="approve(row.id)">审核通过</el-button></template></el-table-column></el-table></el-card>
</section></template>
<script setup lang="ts">
import {watch,onMounted,ref} from 'vue'
import {ElMessage,ElMessageBox} from 'element-plus'
import {preferredSite,rememberSite,sfApi} from './_shared'
interface Site{id:string;name:string}
const sites=ref<Site[]>([]),siteId=ref(''),builds=ref<any[]>([]),requests=ref<any[]>([]),loading=ref(false),csrf=ref('')
async function api(path:string,method='GET',body?:unknown){return sfApi<any>(path,{method,headers:body===undefined?{}:{'Content-Type':'application/json'},body:body===undefined?undefined:JSON.stringify(body)})}
async function reload(){if(!siteId.value)return;loading.value=true;try{[builds.value,requests.value]=await Promise.all([api(`/api/sites/${siteId.value}/builds`),api(`/api/factory/sites/${siteId.value}/release-requests`)])}catch(e:any){ElMessage.error(e.message)}finally{loading.value=false}}
async function review(id:string){try{const r=await api(`/api/factory/sites/${siteId.value}/release-requests`,'POST',{build_id:id});ElMessage.success('审批请求已建立:'+r.id);await reload()}catch(e:any){ElMessage.error(e.message)}}
async function approve(id:string){try{await ElMessageBox.confirm('审批人不能是申请人,是否批准?','审核发布');await api(`/api/factory/sites/${siteId.value}/release-requests/${id}/review`,'POST',{state:'approved'});ElMessage.success('审批完成');await reload()}catch(e:any){if(e!=='cancel')ElMessage.error(e.message)}}
async function deploy(build_id:string,target:'staging'|'production'){try{await ElMessageBox.confirm(`将构建版本 ${build_id} 部署到 ${target},确认目标环境已配置 HTTPS?`,'发布确认');await api(`/api/production/sites/${siteId.value}/deploy`,'POST',{build_id,target});ElMessage.success('远程部署接收端已确认发布')}catch(e:any){if(e!=='cancel')ElMessage.error(e.message)}}
watch(siteId,(id)=>rememberSite(id))
onMounted(async()=>{try{csrf.value=(await api('/api/auth/me')).csrf;sites.value=await api('/api/sites');siteId.value=preferredSite(sites.value);await reload()}catch(e:any){ElMessage.error(e.message)}})
</script>
<style scoped>.release-center h2{font-size:24px;margin:0 0 8px}.release-center p{color:var(--el-text-color-secondary);margin:0 0 25px;font-size:13px}</style>