Skip to content

Commit 5c111e1

Browse files
committed
feat: 添加报告问题对话框,集成调试信息和反馈渠道
1 parent 9fde71f commit 5c111e1

File tree

1 file changed

+152
-4
lines changed

1 file changed

+152
-4
lines changed

src/components/settings/AboutCard.vue

Lines changed: 152 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@
2424
<div class="d-flex gap-2 flex-wrap mb-6">
2525
<v-btn
2626
color="red"
27-
href="https://github.com/ClassworksDev/Classworks/issues"
2827
prepend-icon="mdi-bug"
29-
target="_blank"
3028
variant="tonal"
29+
@click="openReportDialog"
3130
>
3231
报告问题
3332
</v-btn>
@@ -170,6 +169,50 @@
170169
</v-card>
171170
</v-dialog>
172171

172+
<!-- 报告问题对话框 -->
173+
<v-dialog v-model="showReportDialog" max-width="640">
174+
<v-card>
175+
<v-toolbar density="compact">
176+
<v-btn icon="mdi-close" @click="showReportDialog = false"></v-btn>
177+
<v-toolbar-title>报告问题</v-toolbar-title>
178+
<v-spacer></v-spacer>
179+
</v-toolbar>
180+
<v-card-text>
181+
<p class="mb-4">
182+
调试ID与下方的浏览器环境信息将帮助我们快速定位问题,请在反馈中一并附上。
183+
</p>
184+
<v-sheet class="mb-3 pa-3 bg-grey-lighten-4 rounded" style="max-height: 260px; overflow: auto;">
185+
<pre class="text-body-2" style="white-space: pre-wrap; margin: 0;">{{ envBoxText }}</pre>
186+
</v-sheet>
187+
<div class="d-flex gap-2 flex-wrap mb-4">
188+
<v-btn size="small" variant="text" prepend-icon="mdi-refresh" @click="reloadVisitorId" :loading="visitorLoading">刷新</v-btn>
189+
<v-btn size="small" variant="text" prepend-icon="mdi-content-copy" @click="copyEnvInfo">复制信息</v-btn>
190+
<v-btn size="small" variant="text" prepend-icon="mdi-open-in-new" @click="goToDebug">查看 /debug 页面</v-btn>
191+
</div>
192+
<v-alert v-if="copyOk" type="success" density="compact" class="mb-4">已复制到剪贴板</v-alert>
193+
<h4 class="text-subtitle-1 mb-2">反馈渠道</h4>
194+
<v-list lines="one" class="bg-transparent">
195+
<v-list-item :href="qqGroupLink" target="_blank" prepend-icon="mdi-qqchat">
196+
<v-list-item-title>QQ群 ({{ qqGroupNumber }})</v-list-item-title>
197+
<v-list-item-subtitle>964979747</v-list-item-subtitle>
198+
</v-list-item>
199+
<v-list-item :href="githubIssueUrl" target="_blank" prepend-icon="mdi-github">
200+
<v-list-item-title>GitHub Issue</v-list-item-title>
201+
<v-list-item-subtitle>ZeroCatDev/Classworks</v-list-item-subtitle>
202+
</v-list-item>
203+
<v-list-item :href="mailtoLink" target="_blank" prepend-icon="mdi-email">
204+
<v-list-item-title>邮件</v-list-item-title>
205+
<v-list-item-subtitle>sun@wuyuan.dev</v-list-item-subtitle>
206+
</v-list-item>
207+
</v-list>
208+
</v-card-text>
209+
<v-card-actions>
210+
<v-spacer></v-spacer>
211+
<v-btn variant="text" @click="showReportDialog = false">关闭</v-btn>
212+
</v-card-actions>
213+
</v-card>
214+
</v-dialog>
215+
173216
<p class="text-caption text-medium-emphasis">
174217
Copyright © {{ new Date().getFullYear() }} Sunwuyuan
175218
</p>
@@ -181,14 +224,23 @@
181224
</template>
182225

183226
<script>
184-
import {ref, onMounted} from "vue";
227+
import {ref, onMounted, computed} from "vue";
228+
import { useRouter } from 'vue-router'
229+
import { getVisitorId } from '@/utils/fingerprint'
185230
import packageJson from "../../../package.json";
186231
187232
export default {
188233
name: "AboutCard",
189234
setup() {
190235
const Dependencies = ref([]);
191-
const showDeps = ref(false); // 添加对话框显示状态
236+
const showDeps = ref(false);
237+
const showReportDialog = ref(false);
238+
const debugIdInput = ref('');
239+
const visitorLoading = ref(false);
240+
const copyOk = ref(false);
241+
const qqGroupNumber = '964979747';
242+
const qqGroupLink = 'https://qm.qq.com/q/T6qImKJjGi';
243+
const router = useRouter();
192244
193245
const loadDependencies = () => {
194246
try {
@@ -224,13 +276,109 @@ export default {
224276
return descriptions[name] || "";
225277
};
226278
279+
const goToDebug = () => {
280+
router.push('/debug');
281+
};
282+
283+
const loadVisitorId = async () => {
284+
visitorLoading.value = true;
285+
try {
286+
const id = await getVisitorId();
287+
debugIdInput.value = id || '';
288+
} catch (e) {
289+
console.error('获取访客ID失败', e);
290+
} finally {
291+
visitorLoading.value = false;
292+
}
293+
};
294+
295+
const reloadVisitorId = () => loadVisitorId();
296+
297+
const openReportDialog = async () => {
298+
showReportDialog.value = true;
299+
if (!debugIdInput.value) await loadVisitorId();
300+
};
301+
302+
const copyEnvInfo = async () => {
303+
try {
304+
await navigator.clipboard.writeText(envBoxText.value);
305+
copyOk.value = true;
306+
setTimeout(() => (copyOk.value = false), 1800);
307+
} catch (e) {
308+
console.error('复制失败', e);
309+
}
310+
};
311+
312+
const envInfo = computed(() => {
313+
const nav = navigator || {};
314+
const intl = (typeof Intl !== 'undefined' && Intl.DateTimeFormat) ? Intl.DateTimeFormat().resolvedOptions() : {};
315+
const tz = intl && intl.timeZone ? intl.timeZone : '';
316+
const routePath = router.currentRoute?.value?.fullPath || location.pathname;
317+
const lines = [
318+
`App 版本: v${packageJson?.version || 'unknown'}`,
319+
`URL: ${location.href}`,
320+
`路由: ${routePath}`,
321+
`UserAgent: ${nav.userAgent || ''}`,
322+
`语言: ${nav.language || ''}`,
323+
`时区: ${tz}`,
324+
`平台: ${nav.platform || ''}`,
325+
`在线: ${String(nav.onLine)}`,
326+
`屏幕: ${screen?.width || '-'}x${screen?.height || '-'}`,
327+
`视口: ${window.innerWidth || '-'}x${window.innerHeight || '-'}`,
328+
];
329+
return lines.join('\n');
330+
});
331+
332+
const envBoxText = computed(() => {
333+
return `调试ID: ${debugIdInput.value || '获取失败'}\n\n浏览器/环境信息:\n${envInfo.value}`;
334+
});
335+
336+
const reportBody = computed(() => {
337+
return [
338+
`问题描述:`,
339+
`1. 期望行为:`,
340+
`2. 实际行为:`,
341+
`3. 复现步骤:`,
342+
'',
343+
envBoxText.value,
344+
].join('\n');
345+
});
346+
347+
const githubIssueUrl = computed(() => {
348+
const base = 'https://github.com/ZeroCatDev/Classworks/issues/new';
349+
const title = encodeURIComponent('问题报告');
350+
const body = encodeURIComponent(reportBody.value);
351+
return `${base}?title=${title}&body=${body}`;
352+
});
353+
354+
const mailtoLink = computed(() => {
355+
const subject = encodeURIComponent('Classworks 问题报告');
356+
const body = encodeURIComponent(reportBody.value);
357+
return `mailto:sun@wuyuan.dev?subject=${subject}&body=${body}`;
358+
});
359+
227360
onMounted(() => {
228361
loadDependencies();
229362
});
230363
231364
return {
232365
Dependencies,
233366
showDeps,
367+
showReportDialog,
368+
debugIdInput,
369+
visitorLoading,
370+
copyOk,
371+
qqGroupNumber,
372+
qqGroupLink,
373+
goToDebug,
374+
reloadVisitorId,
375+
openReportDialog,
376+
copyEnvInfo,
377+
envBoxText,
378+
envInfo,
379+
reportBody,
380+
githubIssueUrl,
381+
mailtoLink,
234382
};
235383
},
236384
};

0 commit comments

Comments
 (0)