666ghj commited on
Commit
efba59b
·
1 Parent(s): aa6ea31

Enhance Step4Report component with individual selection reason parsing and display

Browse files

- Introduced a new function to parse individual selection reasons from interview text, accommodating multiple formats for better accuracy.
- Updated the interview object to include a selection reason property, ensuring each interview displays the corresponding rationale.
- Enhanced the InterviewDisplay component to render selection reasons with improved styling for better visibility and user experience.

frontend/src/components/Step4Report.vue CHANGED
@@ -661,6 +661,72 @@ const parseInterview = (text) => {
661
  result.selectionReason = reasonMatch[1].trim()
662
  }
663
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  // 提取每个采访记录
665
  const interviewBlocks = text.split(/#### 采访 #\d+:/).slice(1)
666
 
@@ -671,6 +737,7 @@ const parseInterview = (text) => {
671
  name: '',
672
  role: '',
673
  bio: '',
 
674
  questions: [],
675
  twitterAnswer: '',
676
  redditAnswer: '',
@@ -686,6 +753,8 @@ const parseInterview = (text) => {
686
  if (nameRoleMatch) {
687
  interview.name = nameRoleMatch[1].trim()
688
  interview.role = nameRoleMatch[2].trim()
 
 
689
  }
690
 
691
  // 提取简介
@@ -1079,6 +1148,12 @@ const InterviewDisplay = {
1079
  ])
1080
  ]),
1081
 
 
 
 
 
 
 
1082
  // Q&A Conversation Thread - 一问一答样式
1083
  h('div', { class: 'qa-thread' },
1084
  (props.result.interviews[activeIndex.value]?.questions?.length > 0
@@ -3368,6 +3443,30 @@ watch(() => props.reportId, (newId) => {
3368
  overflow: hidden;
3369
  }
3370
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3371
  /* Q&A Thread - Clean list */
3372
  :deep(.interview-display .qa-thread) {
3373
  display: flex;
 
661
  result.selectionReason = reasonMatch[1].trim()
662
  }
663
 
664
+ // 解析每个人的选择理由
665
+ const parseIndividualReasons = (reasonText) => {
666
+ const reasons = {}
667
+ if (!reasonText) return reasons
668
+
669
+ const lines = reasonText.split(/\n+/)
670
+ let currentName = null
671
+ let currentReason = []
672
+
673
+ for (const line of lines) {
674
+ let headerMatch = null
675
+ let name = null
676
+ let reasonStart = null
677
+
678
+ // 格式1: 数字. **名字(index=X)**:理由
679
+ // 例如: 1. **校友_345(index=1)**:作为武大校友...
680
+ headerMatch = line.match(/^\d+\.\s*\*\*([^*((]+)(?:[((]index\s*=?\s*\d+[))])?\*\*[::]\s*(.*)/)
681
+ if (headerMatch) {
682
+ name = headerMatch[1].trim()
683
+ reasonStart = headerMatch[2]
684
+ }
685
+
686
+ // 格式2: - 选择名字(index X):理由
687
+ // 例如: - 选择家长_601(index 0):作为家长群体代表...
688
+ if (!headerMatch) {
689
+ headerMatch = line.match(/^-\s*选择([^((]+)(?:[((]index\s*=?\s*\d+[))])?[::]\s*(.*)/)
690
+ if (headerMatch) {
691
+ name = headerMatch[1].trim()
692
+ reasonStart = headerMatch[2]
693
+ }
694
+ }
695
+
696
+ // 格式3: - **名字(index X)**:理由
697
+ // 例如: - **家长_601(index 0)**:作为家长群体代表...
698
+ if (!headerMatch) {
699
+ headerMatch = line.match(/^-\s*\*\*([^*((]+)(?:[((]index\s*=?\s*\d+[))])?\*\*[::]\s*(.*)/)
700
+ if (headerMatch) {
701
+ name = headerMatch[1].trim()
702
+ reasonStart = headerMatch[2]
703
+ }
704
+ }
705
+
706
+ if (name) {
707
+ // 保存上一个人的理由
708
+ if (currentName && currentReason.length > 0) {
709
+ reasons[currentName] = currentReason.join(' ').trim()
710
+ }
711
+ // 开始新的人
712
+ currentName = name
713
+ currentReason = reasonStart ? [reasonStart.trim()] : []
714
+ } else if (currentName && line.trim() && !line.match(/^未选|^综上|^最终选择/)) {
715
+ // 理由的续行(排除结尾总结段落)
716
+ currentReason.push(line.trim())
717
+ }
718
+ }
719
+
720
+ // 保存最后一个人的理由
721
+ if (currentName && currentReason.length > 0) {
722
+ reasons[currentName] = currentReason.join(' ').trim()
723
+ }
724
+
725
+ return reasons
726
+ }
727
+
728
+ const individualReasons = parseIndividualReasons(result.selectionReason)
729
+
730
  // 提取每个采访记录
731
  const interviewBlocks = text.split(/#### 采访 #\d+:/).slice(1)
732
 
 
737
  name: '',
738
  role: '',
739
  bio: '',
740
+ selectionReason: '',
741
  questions: [],
742
  twitterAnswer: '',
743
  redditAnswer: '',
 
753
  if (nameRoleMatch) {
754
  interview.name = nameRoleMatch[1].trim()
755
  interview.role = nameRoleMatch[2].trim()
756
+ // 设置该人的选择理由
757
+ interview.selectionReason = individualReasons[interview.name] || ''
758
  }
759
 
760
  // 提取简介
 
1148
  ])
1149
  ]),
1150
 
1151
+ // Selection Reason - 选择理由
1152
+ props.result.interviews[activeIndex.value]?.selectionReason && h('div', { class: 'selection-reason' }, [
1153
+ h('div', { class: 'reason-label' }, '选择理由'),
1154
+ h('div', { class: 'reason-content' }, props.result.interviews[activeIndex.value].selectionReason)
1155
+ ]),
1156
+
1157
  // Q&A Conversation Thread - 一问一答样式
1158
  h('div', { class: 'qa-thread' },
1159
  (props.result.interviews[activeIndex.value]?.questions?.length > 0
 
3443
  overflow: hidden;
3444
  }
3445
 
3446
+ /* Selection Reason - 选择理由 */
3447
+ :deep(.interview-display .selection-reason) {
3448
+ background: #F8FAFC;
3449
+ border: 1px solid #E2E8F0;
3450
+ border-radius: 8px;
3451
+ padding: 12px 14px;
3452
+ margin-bottom: 16px;
3453
+ }
3454
+
3455
+ :deep(.interview-display .reason-label) {
3456
+ font-size: 11px;
3457
+ font-weight: 600;
3458
+ color: #64748B;
3459
+ text-transform: uppercase;
3460
+ letter-spacing: 0.03em;
3461
+ margin-bottom: 6px;
3462
+ }
3463
+
3464
+ :deep(.interview-display .reason-content) {
3465
+ font-size: 12px;
3466
+ color: #475569;
3467
+ line-height: 1.6;
3468
+ }
3469
+
3470
  /* Q&A Thread - Clean list */
3471
  :deep(.interview-display .qa-thread) {
3472
  display: flex;