diff --git a/frontend/src/views/EmailDetail/EmailDetail.js b/frontend/src/views/EmailDetail/EmailDetail.js
index d4c066a..fa3a87a 100644
--- a/frontend/src/views/EmailDetail/EmailDetail.js
+++ b/frontend/src/views/EmailDetail/EmailDetail.js
@@ -26,9 +26,13 @@ export function usePage() {
const tos = ref([])
const ccs = ref([])
+
+ const bccs = ref([])
const showCC = ref(false)
+ const showBCC = ref(false)
+
const loading = ref(false)
const loadError = ref('')
let requestSequence = 0
@@ -47,7 +51,9 @@ export function usePage() {
detailData.value = {attachments: []}
tos.value = []
ccs.value = []
+ bccs.value = []
showCC.value = false
+ showBCC.value = false
loadError.value = ''
loading.value = true
@@ -76,6 +82,9 @@ export function usePage() {
tos.value = parseAddresses(data.to)
ccs.value = parseAddresses(data.cc)
showCC.value = ccs.value.length > 0
+ // 仅在本人的发件副本展示密送;后端仍负责所有权校验和收件副本脱敏。
+ bccs.value = data.type === 1 ? parseAddresses(data.bcc) : []
+ showBCC.value = bccs.value.length > 0
} catch {
if (sequence === requestSequence) {
loadError.value = '网络连接失败,请稍后重试'
@@ -165,6 +174,8 @@ export function usePage() {
tos,
ccs,
showCC,
+ bccs,
+ showBCC,
loading,
loadError,
loadDetail,
diff --git a/frontend/src/views/EmailDetail/EmailDetail.vue b/frontend/src/views/EmailDetail/EmailDetail.vue
index 72bb8b7..c954859 100644
--- a/frontend/src/views/EmailDetail/EmailDetail.vue
+++ b/frontend/src/views/EmailDetail/EmailDetail.vue
@@ -61,6 +61,12 @@
{{ item.Name !== '' ? item.Name : item.EmailAddress }},
+
+ {{ lang.bcc }}:
+
+ {{ item.Name || item.EmailAddress }},
+
+
@@ -109,6 +115,8 @@ const {
tos,
showCC,
ccs,
+ showBCC,
+ bccs,
formatDetailDate
} = usePage()
diff --git a/test/frontend/email-detail.test.mjs b/test/frontend/email-detail.test.mjs
index c22a6f9..4378fba 100644
--- a/test/frontend/email-detail.test.mjs
+++ b/test/frontend/email-detail.test.mjs
@@ -79,6 +79,44 @@ test('异常地址和附件字段不导致页面异常,切换邮件清除旧
assert.equal(page.showCC.value, false)
})
+test('仅发件副本展示密送名单,切换到收件副本立即清除', async () => {
+ const addresses = '[{"Name":"","EmailAddress":"hidden@example.com"}]'
+ const {page, route} = fixture(async (_, {id}) => ({
+ errorNo: 0,
+ data: {...email(id).data, type: id === 15 ? 1 : 0, bcc: addresses}
+ }))
+ await settle()
+ assert.equal(page.showBCC.value, true)
+ assert.equal(page.bccs.value[0].EmailAddress, 'hidden@example.com')
+ route.params.id = '16'
+ await settle()
+ assert.equal(page.showBCC.value, false)
+ assert.deepEqual(page.bccs.value, [])
+})
+
+test('未知邮件类型和无效密送字段不展示名单,加载失败不残留旧名单', async () => {
+ for (const data of [
+ {bcc: '[{"EmailAddress":"hidden@example.com"}]'},
+ {type: 1, bcc: '{'},
+ {type: 1, bcc: 'null'},
+ {type: 1, bcc: '[]'}
+ ]) {
+ const {page} = fixture(async () => ({errorNo: 0, data: {...email(15).data, ...data}}))
+ await settle()
+ assert.equal(page.showBCC.value, false)
+ assert.deepEqual(page.bccs.value, [])
+ }
+ const {page, route} = fixture(async (_, {id}) => id === 15
+ ? {errorNo: 0, data: {...email(id).data, type: 1, bcc: '[{"EmailAddress":"hidden@example.com"}]'}}
+ : {errorNo: 403, errorMsg: '无权查看邮件'})
+ await settle()
+ assert.equal(page.showBCC.value, true)
+ route.params.id = '16'
+ await settle()
+ assert.equal(page.showBCC.value, false)
+ assert.deepEqual(page.bccs.value, [])
+})
+
test('切换邮件后旧请求成功或失败均不能覆盖新邮件', async () => {
for (const staleFailure of [false, true]) {
let finish