feat: 限制历史操作为管理员可见

This commit is contained in:
shenlei 2026-07-20 17:18:00 +09:00
parent 13366ab3b4
commit 624f534b0f
2 changed files with 25 additions and 11 deletions

View File

@ -1,4 +1,5 @@
import { describe, it, expect, vi, beforeEach } from 'vitest' import { describe, it, expect, vi, beforeEach } from 'vitest'
import { ref } from 'vue'
import { mount, flushPromises } from '@vue/test-utils' import { mount, flushPromises } from '@vue/test-utils'
import { createRouter, createMemoryHistory } from 'vue-router' import { createRouter, createMemoryHistory } from 'vue-router'
import HistoryView from '../views/HistoryView.vue' import HistoryView from '../views/HistoryView.vue'
@ -22,6 +23,15 @@ function createMockRouter() {
}) })
} }
function mountHistory(admin = false) {
return mount(HistoryView, {
global: {
plugins: [createMockRouter()],
provide: { isAdmin: ref(admin) },
},
})
}
describe('HistoryView.vue', () => { describe('HistoryView.vue', () => {
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks() vi.clearAllMocks()
@ -129,10 +139,7 @@ describe('HistoryView.vue', () => {
}) })
it('已完成任务显示下载按钮', async () => { it('已完成任务显示下载按钮', async () => {
const router = createMockRouter() const wrapper = mountHistory(true)
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises() await flushPromises()
// 第一行App1, completed应该有 dSYM 和下载按钮 // 第一行App1, completed应该有 dSYM 和下载按钮
@ -143,6 +150,15 @@ describe('HistoryView.vue', () => {
expect(firstRow.find('.qr-thumb').exists()).toBe(true) expect(firstRow.find('.qr-thumb').exists()).toBe(true)
}) })
it('普通用户不显示历史操作按钮', async () => {
const wrapper = mountHistory(false)
await flushPromises()
expect(wrapper.find('.action-btns').exists()).toBe(false)
expect(wrapper.text()).not.toContain('删除')
expect(wrapper.text()).not.toContain('日志')
})
it('空列表显示提示', async () => { it('空列表显示提示', async () => {
fetch.mockResolvedValue({ json: () => Promise.resolve([]) }) fetch.mockResolvedValue({ json: () => Promise.resolve([]) })
const router = createMockRouter() const router = createMockRouter()
@ -181,10 +197,7 @@ describe('HistoryView.vue', () => {
}) })
it('点击查看日志打开日志弹窗', async () => { it('点击查看日志打开日志弹窗', async () => {
const router = createMockRouter() const wrapper = mountHistory(true)
const wrapper = mount(HistoryView, {
global: { plugins: [router] },
})
await flushPromises() await flushPromises()
const logBtn = wrapper.findAll('.action-btn').find(b => b.text() === '日志') const logBtn = wrapper.findAll('.action-btn').find(b => b.text() === '日志')

View File

@ -31,7 +31,7 @@
<th>Scheme</th> <th>Scheme</th>
<th>状态</th> <th>状态</th>
<th>下载地址</th> <th>下载地址</th>
<th>操作</th> <th v-if="isAdmin">操作</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -59,7 +59,7 @@
</template> </template>
<span v-else class="text-muted">-</span> <span v-else class="text-muted">-</span>
</td> </td>
<td class="action-btns"> <td v-if="isAdmin" class="action-btns">
<button v-if="task.has_log" class="action-btn" @click="viewLogs(task.id)">日志</button> <button v-if="task.has_log" class="action-btn" @click="viewLogs(task.id)">日志</button>
<button v-if="task.status === 'completed' && task.dsym_path" class="action-btn" @click="downloadDsym(task.id)">dSYM</button> <button v-if="task.status === 'completed' && task.dsym_path" class="action-btn" @click="downloadDsym(task.id)">dSYM</button>
<button v-if="task.obfuscation_maps_path" class="action-btn" @click="downloadObfMaps(task.id)">混淆映射</button> <button v-if="task.obfuscation_maps_path" class="action-btn" @click="downloadObfMaps(task.id)">混淆映射</button>
@ -67,7 +67,7 @@
</td> </td>
</tr> </tr>
<tr v-if="!filteredTasks.length"> <tr v-if="!filteredTasks.length">
<td colspan="7" style="text-align: center; color: #999; padding: 40px;">暂无打包记录</td> <td :colspan="isAdmin ? 7 : 6" style="text-align: center; color: #999; padding: 40px;">暂无打包记录</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -161,6 +161,7 @@
import { ref, computed, onMounted, nextTick, onUnmounted, inject } from 'vue' import { ref, computed, onMounted, nextTick, onUnmounted, inject } from 'vue'
const getToken = inject('getToken', () => '') const getToken = inject('getToken', () => '')
const isAdmin = inject('isAdmin', ref(false))
const tasks = ref([]) const tasks = ref([])
const authFetch = (url, options = {}) => { const authFetch = (url, options = {}) => {