|
@@ -11,6 +11,18 @@
|
|
|
<text class="tip-text">请核对以下解析内容,可修改后确认入库</text>
|
|
<text class="tip-text">请核对以下解析内容,可修改后确认入库</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
|
|
+ <!-- 匹配可信度 -->
|
|
|
|
|
+ <view class="confidence-card" v-if="confidenceLevelClass">
|
|
|
|
|
+ <view class="confidence-header">
|
|
|
|
|
+ <text class="confidence-label">匹配可信度</text>
|
|
|
|
|
+ <text class="confidence-badge" :class="'badge-' + confidenceLevelClass">{{ confidenceLevelText }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="confidence-bar-track">
|
|
|
|
|
+ <view class="confidence-bar-fill" :class="'fill-' + confidenceLevelClass" :style="'width:' + confidencePercent + '%'"></view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <text class="confidence-desc">{{ confidenceDesc }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
<view class="form-section">
|
|
<view class="form-section">
|
|
|
<!-- 基本信息 -->
|
|
<!-- 基本信息 -->
|
|
|
<view class="card">
|
|
<view class="card">
|
|
@@ -20,6 +32,14 @@
|
|
|
<text class="field-value" v-if="!needBind">{{ extractedName || '未识别' }}</text>
|
|
<text class="field-value" v-if="!needBind">{{ extractedName || '未识别' }}</text>
|
|
|
<text class="field-value binding-required" v-else>需手动绑定</text>
|
|
<text class="field-value binding-required" v-else>需手动绑定</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <view class="field-row" v-if="extractedGender">
|
|
|
|
|
+ <text class="field-label">性别</text>
|
|
|
|
|
+ <text class="field-value">{{ extractedGender === 'male' ? '男' : extractedGender === 'female' ? '女' : extractedGender }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="field-row" v-if="extractedAge">
|
|
|
|
|
+ <text class="field-label">年龄</text>
|
|
|
|
|
+ <text class="field-value">{{ extractedAge }}</text>
|
|
|
|
|
+ </view>
|
|
|
<view class="field-row" v-if="payload.summary">
|
|
<view class="field-row" v-if="payload.summary">
|
|
|
<text class="field-label">综合评分</text>
|
|
<text class="field-label">综合评分</text>
|
|
|
<input class="field-input" type="number" v-model="payload.summary.overallScore" />
|
|
<input class="field-input" type="number" v-model="payload.summary.overallScore" />
|
|
@@ -30,21 +50,80 @@
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
- <!-- 家庭成员绑定 -->
|
|
|
|
|
|
|
+ <!-- 家庭成员绑定(含候选推荐) -->
|
|
|
<view class="card" v-if="needBind">
|
|
<view class="card" v-if="needBind">
|
|
|
- <view class="card-title">绑定家庭成员</view>
|
|
|
|
|
- <view class="member-list">
|
|
|
|
|
|
|
+ <view class="card-title">选择家庭成员</view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 候选匹配列表(按置信度排序) -->
|
|
|
|
|
+ <view class="candidate-section" v-if="candidates.length > 0">
|
|
|
|
|
+ <text class="candidate-section-hint">以下成员与报告信息匹配,请选择:</text>
|
|
|
|
|
+ <view
|
|
|
|
|
+ class="candidate-item"
|
|
|
|
|
+ v-for="(cand, idx) in candidates"
|
|
|
|
|
+ :key="cand.id || idx"
|
|
|
|
|
+ :class="{ 'candidate-selected': selectedMemberId === (cand.id || cand.userId) }"
|
|
|
|
|
+ @click="selectCandidate(cand)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <view class="candidate-left">
|
|
|
|
|
+ <text class="candidate-avatar">{{ (cand.nickname || cand.name || '?').substring(0, 1) }}</text>
|
|
|
|
|
+ <view class="candidate-info">
|
|
|
|
|
+ <text class="candidate-name">{{ cand.nickname || cand.name || '未知' }}</text>
|
|
|
|
|
+ <text class="candidate-detail" v-if="cand.gender || cand.age">{{ genderText(cand.gender) }}{{ cand.age ? ' · ' + cand.age + '岁' : '' }}</text>
|
|
|
|
|
+ <text class="candidate-fields" v-if="cand.matchFields">匹配: {{ cand.matchFields }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="candidate-right">
|
|
|
|
|
+ <view class="score-bar-track">
|
|
|
|
|
+ <view class="score-bar-fill" :style="'width:' + (cand.similarityScore * 100) + '%'"></view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <text class="score-text">{{ Math.round(cand.similarityScore * 100) }}%</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 全量家庭成员列表(后备) -->
|
|
|
|
|
+ <view class="member-list" v-if="familyMembers.length > 0 && (candidates.length === 0 || !showCandidatesOnly)">
|
|
|
<view
|
|
<view
|
|
|
class="member-item"
|
|
class="member-item"
|
|
|
v-for="member in familyMembers"
|
|
v-for="member in familyMembers"
|
|
|
- :key="member.userId"
|
|
|
|
|
- :class="{ 'member-selected': selectedMemberId === member.userId }"
|
|
|
|
|
|
|
+ :key="member.userId || member.id"
|
|
|
|
|
+ :class="{ 'member-selected': selectedMemberId === (member.userId || member.id) }"
|
|
|
@click="selectMember(member)"
|
|
@click="selectMember(member)"
|
|
|
>
|
|
>
|
|
|
- <text class="member-avatar">{{ member.nickname && member.nickname.substring(0, 1) || '?' }}</text>
|
|
|
|
|
|
|
+ <text class="member-avatar">{{ (member.nickname || '?').substring(0, 1) }}</text>
|
|
|
<text class="member-name">{{ member.nickname || '未知' }}</text>
|
|
<text class="member-name">{{ member.nickname || '未知' }}</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 新建成员入口 -->
|
|
|
|
|
+ <view class="create-member-entry" @click="toggleAutoCreate">
|
|
|
|
|
+ <text class="create-member-icon">+</text>
|
|
|
|
|
+ <text class="create-member-text">{{ showAutoCreateForm ? '收起新建表单' : '不在列表中?新建家庭成员' }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 新建家庭成员表单 -->
|
|
|
|
|
+ <view class="card auto-create-card" v-if="showAutoCreateForm">
|
|
|
|
|
+ <view class="card-title">新建家庭成员</view>
|
|
|
|
|
+ <view class="form-item">
|
|
|
|
|
+ <text class="form-item-label">姓名</text>
|
|
|
|
|
+ <input class="form-item-input" v-model="newMember.name" placeholder="请输入姓名" />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="form-item">
|
|
|
|
|
+ <text class="form-item-label">性别</text>
|
|
|
|
|
+ <view class="gender-selector">
|
|
|
|
|
+ <text class="gender-option" :class="{ 'gender-selected': newMember.gender === 'male' }" @click="newMember.gender = 'male'">男</text>
|
|
|
|
|
+ <text class="gender-option" :class="{ 'gender-selected': newMember.gender === 'female' }" @click="newMember.gender = 'female'">女</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="form-item">
|
|
|
|
|
+ <text class="form-item-label">年龄</text>
|
|
|
|
|
+ <input class="form-item-input" type="number" v-model="newMember.age" placeholder="请输入年龄" />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="btn-create-submit" :class="{ 'btn-disabled': creatingMember }" @click="doAutoCreate">
|
|
|
|
|
+ <text v-if="creatingMember">创建中...</text>
|
|
|
|
|
+ <text v-else>确认创建</text>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 健康指标 -->
|
|
<!-- 健康指标 -->
|
|
@@ -121,6 +200,7 @@
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
import { confirmReportPreview, discardReportDraft } from '../../utils/api.js'
|
|
import { confirmReportPreview, discardReportDraft } from '../../utils/api.js'
|
|
|
|
|
+import { addFamilyMember } from '../../utils/api.js'
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
data() {
|
|
data() {
|
|
@@ -137,17 +217,56 @@ export default {
|
|
|
diseaseRisks: []
|
|
diseaseRisks: []
|
|
|
},
|
|
},
|
|
|
extractedName: '',
|
|
extractedName: '',
|
|
|
|
|
+ extractedGender: '',
|
|
|
|
|
+ extractedAge: '',
|
|
|
matchedMemberId: null,
|
|
matchedMemberId: null,
|
|
|
needBind: false,
|
|
needBind: false,
|
|
|
selectedMemberId: null,
|
|
selectedMemberId: null,
|
|
|
familyMembers: [],
|
|
familyMembers: [],
|
|
|
- confirming: false
|
|
|
|
|
|
|
+ confirming: false,
|
|
|
|
|
+ // Phase 2: 匹配可信度与候选
|
|
|
|
|
+ matchConfidence: null,
|
|
|
|
|
+ matchLabel: '',
|
|
|
|
|
+ candidates: [],
|
|
|
|
|
+ showCandidatesOnly: false,
|
|
|
|
|
+ // 新建成员
|
|
|
|
|
+ showAutoCreateForm: false,
|
|
|
|
|
+ newMember: {
|
|
|
|
|
+ name: '',
|
|
|
|
|
+ gender: '',
|
|
|
|
|
+ age: ''
|
|
|
|
|
+ },
|
|
|
|
|
+ creatingMember: false,
|
|
|
|
|
+ createdMemberId: null
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
computed: {
|
|
computed: {
|
|
|
canConfirm() {
|
|
canConfirm() {
|
|
|
- if (this.needBind && !this.selectedMemberId) return false
|
|
|
|
|
|
|
+ if (this.needBind && !this.selectedMemberId && !this.createdMemberId) return false
|
|
|
return this.draftId && !this.confirming
|
|
return this.draftId && !this.confirming
|
|
|
|
|
+ },
|
|
|
|
|
+ confidenceLevelClass() {
|
|
|
|
|
+ if (!this.matchConfidence && this.matchConfidence !== 0) return ''
|
|
|
|
|
+ var val = parseFloat(this.matchConfidence)
|
|
|
|
|
+ if (this.matchLabel === 'exact' || val >= 0.8) return 'high'
|
|
|
|
|
+ if (this.matchLabel === 'fuzzy' || val >= 0.5) return 'medium'
|
|
|
|
|
+ if (this.matchLabel === 'profile_match' || val >= 0.2) return 'low'
|
|
|
|
|
+ return 'none'
|
|
|
|
|
+ },
|
|
|
|
|
+ confidenceLevelText() {
|
|
|
|
|
+ var map = { high: '高', medium: '中', low: '低', none: '未匹配' }
|
|
|
|
|
+ return map[this.confidenceLevelClass] || ''
|
|
|
|
|
+ },
|
|
|
|
|
+ confidencePercent() {
|
|
|
|
|
+ if (!this.matchConfidence && this.matchConfidence !== 0) return 0
|
|
|
|
|
+ return Math.round(parseFloat(this.matchConfidence) * 100)
|
|
|
|
|
+ },
|
|
|
|
|
+ confidenceDesc() {
|
|
|
|
|
+ if (this.matchLabel === 'exact') return '根据姓名、性别、年龄自动精确匹配到家庭成员'
|
|
|
|
|
+ if (this.matchLabel === 'fuzzy') return '部分字段匹配,请确认是否为以下家庭成员'
|
|
|
|
|
+ if (this.matchLabel === 'profile_match') return '根据档案信息推测匹配,请手动确认'
|
|
|
|
|
+ if (this.matchLabel === 'no_match') return '无法匹配到现有家庭成员,可新建成员'
|
|
|
|
|
+ return ''
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
onLoad: function(options) {
|
|
onLoad: function(options) {
|
|
@@ -171,11 +290,34 @@ export default {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.extractedName = options.extractedName || ''
|
|
this.extractedName = options.extractedName || ''
|
|
|
|
|
+ this.extractedGender = options.extractedGender || ''
|
|
|
|
|
+ this.extractedAge = options.extractedAge || ''
|
|
|
this.matchedMemberId = options.matchedMemberId ? parseInt(options.matchedMemberId) : null
|
|
this.matchedMemberId = options.matchedMemberId ? parseInt(options.matchedMemberId) : null
|
|
|
this.needBind = options.needBind === 'true' || options.needBind === '1'
|
|
this.needBind = options.needBind === 'true' || options.needBind === '1'
|
|
|
|
|
+ this.matchConfidence = options.matchConfidence ? parseFloat(options.matchConfidence) : null
|
|
|
|
|
+ this.matchLabel = decodeURIComponent(options.matchLabel || '')
|
|
|
|
|
+
|
|
|
|
|
+ // 解析候选成员列表
|
|
|
|
|
+ var candidatesStr = decodeURIComponent(options.candidates || '')
|
|
|
|
|
+ if (candidatesStr) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ this.candidates = JSON.parse(candidatesStr)
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ this.candidates = []
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 有候选时优先展示候选列表
|
|
|
|
|
+ if (this.candidates.length > 0) {
|
|
|
|
|
+ this.showCandidatesOnly = true
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if (this.needBind) {
|
|
if (this.needBind) {
|
|
|
this.loadFamilyMembers()
|
|
this.loadFamilyMembers()
|
|
|
|
|
+ // 高置信度且已匹配 → 直接选中
|
|
|
|
|
+ if (this.matchedMemberId && this.matchConfidence >= 0.8) {
|
|
|
|
|
+ this.selectedMemberId = this.matchedMemberId
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
@@ -192,6 +334,58 @@ export default {
|
|
|
selectMember(member) {
|
|
selectMember(member) {
|
|
|
this.selectedMemberId = member.userId || member.id
|
|
this.selectedMemberId = member.userId || member.id
|
|
|
},
|
|
},
|
|
|
|
|
+ // === Phase 2: 候选匹配与新建成员 ===
|
|
|
|
|
+ genderText(gender) {
|
|
|
|
|
+ if (gender === 'male') return '男'
|
|
|
|
|
+ if (gender === 'female') return '女'
|
|
|
|
|
+ return gender || ''
|
|
|
|
|
+ },
|
|
|
|
|
+ selectCandidate(candidate) {
|
|
|
|
|
+ this.selectedMemberId = candidate.id || candidate.userId
|
|
|
|
|
+ this.showAutoCreateForm = false
|
|
|
|
|
+ },
|
|
|
|
|
+ toggleAutoCreate() {
|
|
|
|
|
+ this.showAutoCreateForm = !this.showAutoCreateForm
|
|
|
|
|
+ if (this.showAutoCreateForm) {
|
|
|
|
|
+ this.newMember.name = this.extractedName || ''
|
|
|
|
|
+ this.newMember.gender = this.extractedGender || ''
|
|
|
|
|
+ this.newMember.age = this.extractedAge || ''
|
|
|
|
|
+ this.selectedMemberId = null
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ doAutoCreate() {
|
|
|
|
|
+ var self = this
|
|
|
|
|
+ if (!this.newMember.name) {
|
|
|
|
|
+ uni.showToast({ title: '请输入成员姓名', icon: 'none' })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ self.creatingMember = true
|
|
|
|
|
+ uni.showLoading({ title: '创建成员...' })
|
|
|
|
|
+
|
|
|
|
|
+ addFamilyMember({
|
|
|
|
|
+ nickname: self.newMember.name,
|
|
|
|
|
+ gender: self.newMember.gender || '',
|
|
|
|
|
+ age: self.newMember.age ? parseInt(self.newMember.age) : null
|
|
|
|
|
+ }).then(function(res) {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ if (res.code === 200) {
|
|
|
|
|
+ var memberId = res.data && (res.data.userId || res.data.id)
|
|
|
|
|
+ if (memberId) {
|
|
|
|
|
+ self.createdMemberId = memberId
|
|
|
|
|
+ self.selectedMemberId = memberId
|
|
|
|
|
+ self.showAutoCreateForm = false
|
|
|
|
|
+ uni.showToast({ title: '创建成功', icon: 'success' })
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.showToast({ title: res.message || '创建失败', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch(function(e) {
|
|
|
|
|
+ uni.hideLoading()
|
|
|
|
|
+ uni.showToast({ title: '创建失败', icon: 'none' })
|
|
|
|
|
+ }).finally(function() {
|
|
|
|
|
+ self.creatingMember = false
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
statusText(status) {
|
|
statusText(status) {
|
|
|
if (status === 'high') return '偏高'
|
|
if (status === 'high') return '偏高'
|
|
|
if (status === 'low') return '偏低'
|
|
if (status === 'low') return '偏低'
|
|
@@ -213,8 +407,11 @@ export default {
|
|
|
draftId: self.draftId,
|
|
draftId: self.draftId,
|
|
|
payload: self.payload
|
|
payload: self.payload
|
|
|
}
|
|
}
|
|
|
- if (self.needBind && self.selectedMemberId) {
|
|
|
|
|
|
|
+ // 优先级: 已选成员 > 新建成员 > 自动匹配(高置信度) > 子ID
|
|
|
|
|
+ if (self.selectedMemberId) {
|
|
|
postData.subjectId = self.selectedMemberId
|
|
postData.subjectId = self.selectedMemberId
|
|
|
|
|
+ } else if (self.createdMemberId) {
|
|
|
|
|
+ postData.subjectId = self.createdMemberId
|
|
|
} else if (self.matchedMemberId) {
|
|
} else if (self.matchedMemberId) {
|
|
|
postData.subjectId = self.matchedMemberId
|
|
postData.subjectId = self.matchedMemberId
|
|
|
} else if (self.childId) {
|
|
} else if (self.childId) {
|
|
@@ -584,4 +781,231 @@ export default {
|
|
|
.btn-disabled { opacity: 0.5; }
|
|
.btn-disabled { opacity: 0.5; }
|
|
|
|
|
|
|
|
.bottom-spacer { height: 80rpx; }
|
|
.bottom-spacer { height: 80rpx; }
|
|
|
|
|
+
|
|
|
|
|
+/* ===== Phase 2: 匹配可信度 ===== */
|
|
|
|
|
+.confidence-card {
|
|
|
|
|
+ margin: 0 30rpx 20rpx;
|
|
|
|
|
+ background: #fff;
|
|
|
|
|
+ border-radius: 16rpx;
|
|
|
|
|
+ padding: 24rpx;
|
|
|
|
|
+ box-shadow: 0 2rpx 6rpx rgba(0,0,0,0.04);
|
|
|
|
|
+}
|
|
|
|
|
+.confidence-header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ margin-bottom: 16rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.confidence-label {
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+.confidence-badge {
|
|
|
|
|
+ font-size: 22rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ padding: 4rpx 16rpx;
|
|
|
|
|
+ border-radius: 20rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.badge-high { background: #E8F5E9; color: #2E7D32; }
|
|
|
|
|
+.badge-medium { background: #FFF8E1; color: #F57F17; }
|
|
|
|
|
+.badge-low { background: #FFF3E0; color: #E65100; }
|
|
|
|
|
+.badge-none { background: #FFEBEE; color: #C62828; }
|
|
|
|
|
+
|
|
|
|
|
+.confidence-bar-track {
|
|
|
|
|
+ height: 12rpx;
|
|
|
|
|
+ background: #E2E8F0;
|
|
|
|
|
+ border-radius: 6rpx;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ margin-bottom: 12rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.confidence-bar-fill {
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ border-radius: 6rpx;
|
|
|
|
|
+ transition: width 0.3s ease;
|
|
|
|
|
+}
|
|
|
|
|
+.fill-high { background: linear-gradient(90deg, #66BB6A, #43A047); }
|
|
|
|
|
+.fill-medium { background: linear-gradient(90deg, #FFD54F, #FFC107); }
|
|
|
|
|
+.fill-low { background: linear-gradient(90deg, #FF8A65, #FF5722); }
|
|
|
|
|
+.fill-none { background: linear-gradient(90deg, #EF9A9A, #E53935); }
|
|
|
|
|
+
|
|
|
|
|
+.confidence-desc {
|
|
|
|
|
+ font-size: 22rpx;
|
|
|
|
|
+ color: #94A3B8;
|
|
|
|
|
+ line-height: 1.4;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== Phase 2: 候选成员列表 ===== */
|
|
|
|
|
+.candidate-section {
|
|
|
|
|
+ margin-bottom: 16rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-section-hint {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #64748B;
|
|
|
|
|
+ margin-bottom: 12rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ padding: 16rpx;
|
|
|
|
|
+ background: #F8FAFB;
|
|
|
|
|
+ border-radius: 12rpx;
|
|
|
|
|
+ margin-bottom: 10rpx;
|
|
|
|
|
+ border: 2rpx solid transparent;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-item:active { opacity: 0.8; }
|
|
|
|
|
+.candidate-selected {
|
|
|
|
|
+ background: #E3F2FD;
|
|
|
|
|
+ border-color: #5B9BD5;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-left {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-avatar {
|
|
|
|
|
+ width: 56rpx;
|
|
|
|
|
+ height: 56rpx;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background: #5B9BD5;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ line-height: 56rpx;
|
|
|
|
|
+ margin-right: 16rpx;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-info {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ min-width: 0;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-name {
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-detail {
|
|
|
|
|
+ font-size: 22rpx;
|
|
|
|
|
+ color: #94A3B8;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-fields {
|
|
|
|
|
+ font-size: 20rpx;
|
|
|
|
|
+ color: #5B9BD5;
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ margin-top: 2rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.candidate-right {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 12rpx;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ margin-left: 16rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.score-bar-track {
|
|
|
|
|
+ width: 80rpx;
|
|
|
|
|
+ height: 10rpx;
|
|
|
|
|
+ background: #E2E8F0;
|
|
|
|
|
+ border-radius: 5rpx;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+.score-bar-fill {
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ background: linear-gradient(90deg, #5B9BD5, #3A7CC4);
|
|
|
|
|
+ border-radius: 5rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.score-text {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #1565C0;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ min-width: 48rpx;
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== Phase 2: 新建成员入口 ===== */
|
|
|
|
|
+.create-member-entry {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ padding: 20rpx;
|
|
|
|
|
+ border: 2rpx dashed #CBD5E1;
|
|
|
|
|
+ border-radius: 12rpx;
|
|
|
|
|
+ margin-top: 8rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.create-member-entry:active { background: #F1F5F9; }
|
|
|
|
|
+.create-member-icon {
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ color: #5B9BD5;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ margin-right: 8rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.create-member-text {
|
|
|
|
|
+ font-size: 24rpx;
|
|
|
|
|
+ color: #5B9BD5;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== Phase 2: 新建成员表单 ===== */
|
|
|
|
|
+.auto-create-card {
|
|
|
|
|
+ border: 2rpx solid #E3F2FD;
|
|
|
|
|
+}
|
|
|
|
|
+.form-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 20rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.form-item-label {
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ width: 100rpx;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+}
|
|
|
|
|
+.form-item-input {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ padding: 12rpx 16rpx;
|
|
|
|
|
+ background: #F5F7FA;
|
|
|
|
|
+ border-radius: 10rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.gender-selector {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ gap: 16rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.gender-option {
|
|
|
|
|
+ font-size: 26rpx;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ padding: 12rpx 32rpx;
|
|
|
|
|
+ background: #F5F7FA;
|
|
|
|
|
+ border-radius: 10rpx;
|
|
|
|
|
+ border: 2rpx solid transparent;
|
|
|
|
|
+}
|
|
|
|
|
+.gender-option:active { opacity: 0.7; }
|
|
|
|
|
+.gender-selected {
|
|
|
|
|
+ background: #E3F2FD;
|
|
|
|
|
+ border-color: #5B9BD5;
|
|
|
|
|
+ color: #1565C0;
|
|
|
|
|
+}
|
|
|
|
|
+.btn-create-submit {
|
|
|
|
|
+ background: linear-gradient(135deg, #5B9BD5, #3A7CC4);
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-size: 28rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ padding: 22rpx;
|
|
|
|
|
+ border-radius: 14rpx;
|
|
|
|
|
+ margin-top: 10rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.btn-create-submit:active { opacity: 0.85; }
|
|
|
</style>
|
|
</style>
|