From 51d7374f2d3547182de84da9b6e3fe170d63a964 Mon Sep 17 00:00:00 2001 From: shenlei Date: Mon, 20 Jul 2026 15:28:02 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=8F=90=E7=A4=BA=E6=89=93=E5=8C=85?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=B9=B6=E9=87=8D=E7=BD=AE=E8=A1=A8=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/__tests__/BuildView.test.js | 51 +++++++++++++++++------- frontend/src/views/BuildView.vue | 24 +++++++++-- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/frontend/src/__tests__/BuildView.test.js b/frontend/src/__tests__/BuildView.test.js index 5507ed5..1712099 100644 --- a/frontend/src/__tests__/BuildView.test.js +++ b/frontend/src/__tests__/BuildView.test.js @@ -1,5 +1,6 @@ import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount, flushPromises } from '@vue/test-utils' +import { createMemoryHistory, createRouter } from 'vue-router' import BuildView from '../views/BuildView.vue' global.fetch = vi.fn() @@ -11,12 +12,25 @@ class MockWebSocket { } global.WebSocket = MockWebSocket +const mountBuildView = () => { + const router = createRouter({ + history: createMemoryHistory(), + routes: [{ path: '/', component: BuildView }], + }) + return mount(BuildView, { + global: { + plugins: [router], + provide: { getToken: () => '' }, + }, + }) +} + describe('BuildView.vue', () => { beforeEach(() => { vi.clearAllMocks() fetch.mockImplementation((url) => { const responses = { - '/api/apps': { '1': { name: '测试App', server: '测试环境' } }, + '/api/apps': { '1': { name: '测试App', server: '测试环境', certificates: { Ad_Hoc: {} } } }, '/api/schemes': { '1': { name: 'testScheme' } }, '/api/branches': ['main', 'dev'], '/api/tasks': [], @@ -28,7 +42,7 @@ describe('BuildView.vue', () => { }) it('显示打包配置面板', async () => { - const wrapper = mount(BuildView) + const wrapper = mountBuildView() await flushPromises() expect(wrapper.text()).toContain('打包配置') @@ -39,15 +53,17 @@ describe('BuildView.vue', () => { }) it('加载 apps 和 schemes', async () => { - const wrapper = mount(BuildView) + const wrapper = mountBuildView() await flushPromises() - const appOptions = wrapper.findAll('select')[0].findAll('option') + wrapper.vm.selectedServer = '测试环境' + await wrapper.vm.$nextTick() + const appOptions = wrapper.findAll('select')[1].findAll('option') expect(appOptions.length).toBeGreaterThan(1) }) it('加载分支列表并显示下拉', async () => { - const wrapper = mount(BuildView) + const wrapper = mountBuildView() await flushPromises() const branchSelect = wrapper.findAll('select').find(s => { @@ -58,10 +74,10 @@ describe('BuildView.vue', () => { }) it('默认值正确', async () => { - const wrapper = mount(BuildView) + const wrapper = mountBuildView() await flushPromises() - expect(wrapper.vm.form.build_type).toBe('Ad_Hoc') + expect(wrapper.vm.form.build_type).toBe('') expect(wrapper.vm.form.obfuscation).toBe(false) expect(wrapper.vm.form.branch).toBe('main') }) @@ -75,7 +91,7 @@ describe('BuildView.vue', () => { }) } const responses = { - '/api/apps': { '1': { name: '测试App', server: '测试环境' } }, + '/api/apps': { '1': { name: '测试App', server: '测试环境', certificates: { Ad_Hoc: {} } } }, '/api/schemes': { '1': { name: 'testScheme' } }, '/api/branches': ['main', 'dev'], '/api/tasks': [], @@ -85,21 +101,28 @@ describe('BuildView.vue', () => { }) }) - const wrapper = mount(BuildView) + const wrapper = mountBuildView() await flushPromises() - await wrapper.setData({ form: { ...wrapper.vm.form, app_id: '1' } }) + wrapper.vm.selectedServer = '测试环境' + await wrapper.vm.$nextTick() + wrapper.vm.form.app_id = '1' + await wrapper.vm.$nextTick() await wrapper.find('.btn-primary').trigger('click') await flushPromises() expect(fetch).toHaveBeenCalledWith('/api/tasks', expect.objectContaining({ method: 'POST', })) + expect(wrapper.text()).toContain('打包任务已创建,正在排队,请勿重复点击。') + expect(wrapper.vm.form.app_id).toBe('') + expect(wrapper.vm.form.build_type).toBe('') + expect(wrapper.vm.form.scheme_id).toBe('') }) it('未选择 App 时提示', async () => { window.alert = vi.fn() - const wrapper = mount(BuildView) + const wrapper = mountBuildView() await flushPromises() await wrapper.find('.btn-primary').trigger('click') @@ -109,7 +132,7 @@ describe('BuildView.vue', () => { it('显示任务队列', async () => { fetch.mockImplementation((url) => { const responses = { - '/api/apps': { '1': { name: '测试App', server: '测试环境' } }, + '/api/apps': { '1': { name: '测试App', server: '测试环境', certificates: { Ad_Hoc: {} } } }, '/api/schemes': { '1': { name: 'testScheme' } }, '/api/branches': ['main', 'dev'], '/api/tasks': [ @@ -122,7 +145,7 @@ describe('BuildView.vue', () => { }) }) - const wrapper = mount(BuildView) + const wrapper = mountBuildView() await flushPromises() const taskItems = wrapper.findAll('.task-item') @@ -130,7 +153,7 @@ describe('BuildView.vue', () => { }) it('状态文本正确', async () => { - const wrapper = mount(BuildView) + const wrapper = mountBuildView() await flushPromises() expect(wrapper.vm.statusText('pending')).toBe('等待中') diff --git a/frontend/src/views/BuildView.vue b/frontend/src/views/BuildView.vue index 36fa86f..baf96bb 100644 --- a/frontend/src/views/BuildView.vue +++ b/frontend/src/views/BuildView.vue @@ -53,6 +53,7 @@ +

{{ submitNotice }}

@@ -193,6 +194,7 @@ const form = ref({ branch: 'main', }) const submitting = ref(false) +const submitNotice = ref('') const currentTaskId = ref(null) const completedTask = ref(null) const logs = ref([]) @@ -294,7 +296,12 @@ watch(selectedServer, () => { form.value.app_id = '' }) -watch(() => form.value.app_id, () => { +watch(() => form.value.app_id, (appId) => { + if (!appId) { + form.value.scheme_id = '' + form.value.build_type = '' + return + } form.value.scheme_id = filteredSchemes.value[0]?.[0] || '' form.value.build_type = availableBuildTypes.value[0] || '' }) @@ -347,6 +354,7 @@ onMounted(async () => { }) const submitTask = async () => { + if (submitting.value) return if (!form.value.app_id) { alert('请选择 App') return @@ -362,11 +370,20 @@ const submitTask = async () => { const task = await res.json() currentTaskId.value = task.id tasks.value.unshift(task) + submitNotice.value = '打包任务已创建,正在排队,请勿重复点击。' + selectedServer.value = '' + form.value = { + app_id: '', + build_type: '', + scheme_id: '', + obfuscation: false, + branch: branches.value[0] || 'main', + } } else { - alert('提交失败') + submitNotice.value = '提交失败,请检查配置后重试。' } } catch (e) { - alert('提交失败') + submitNotice.value = '提交失败,请检查网络后重试。' } finally { submitting.value = false } @@ -443,6 +460,7 @@ const errorCategoryHint = (cat) => { .btn-primary { background: #1890ff; color: white; } .btn-primary:hover { background: #40a9ff; } .btn-primary:disabled { background: #d9d9d9; cursor: not-allowed; } +.submit-notice { margin: 0 0 12px; padding: 9px 12px; border-radius: 6px; background: #e6f7ff; color: #096dd9; font-size: 13px; line-height: 1.5; } .btn-danger { background: #ff4d4f; color: white; } .right-panel { display: flex; flex-direction: column; gap: 16px; height: calc(100vh - 120px); overflow: hidden; }