Commit 3f614b3b authored by marsandheart's avatar marsandheart

问题页面半成品

parent fc9b4394
@import '../DoubleRecord.module.scss';
.stepQuestionItem{
position: relative;
margin-bottom: 0.32rem;
display: flex;
.leftIcon{
width: 0.4rem;
height: 0.4rem;
}
.itemText{
background-color: #E1DEE6;
font-weight: bold;
width: 8.2rem;
min-height: 0.6rem;
padding: 0.1rem;
margin-left: 0.1rem;
border-radius: 5px;
font-size: 16px;
}
.rightIcon{
width: 0.3rem;
height: 0.3rem;
position: absolute;
bottom: 0;
right: 0;
}
}
.hide{
width: 0.4rem;
height: 0.4rem;
visibility: hidden;
}
\ No newline at end of file
import React, { useState } from 'react';
import styles from './Question.module.scss';
import TouchOpacity from 'components/TouchOpacity';
import IconPlay from 'assets/img/play.png';
import IconPlayDefault from 'assets/img/play_default.png';
import IconPause from 'assets/img/pause.png';
import IconCheckBlue from 'assets/img/check-square-blue.png';
import IconCheckDefaultBlue from 'assets/img/check_default-square-blue.png';
import IconCheckRed from 'assets/img/check-square-red.png';
import IconCheckDefaultRed from 'assets/img/check_default-square-red.png';
// question不一定都是问题,也可能是答案,其实分为需要读/不需要读 和 需要操作/不需要操作
export default function(props) {
const { question, setPlayStatus, setChecked, voiceStart, voicePause, voiceContinue } = props;
const { questionId, needPlay, needCheck, text, voice, playStatus, checked } = question;
// 0 未开始-无图标;1 播放中-显示暂停图标;2 暂停中-显示播放图标; 3 已结束-显示灰色播放图标
// const [playStatus, setPlayStatus] = useState('0');
// const [checked, setChecked] = useState(false);
const getPlayIcon = () => {
if (playStatus === '3') {
return IconPlayDefault;
} else if (playStatus === '2') {
return IconPlay;
} else if (playStatus === '1') {
return IconPause;
}
return null;
};
const getCheckIcon = () => {
if (needCheck && checked) {
return IconCheckRed;
} else if (needCheck && !checked) {
return IconCheckDefaultRed;
} else if (!needCheck && checked) {
return IconCheckBlue;
} else if (!needCheck && !checked) {
return IconCheckDefaultBlue;
}
return IconCheckBlue;
};
const playOrPause = () => {
console.log({ question });
if (playStatus === '2') {
setPlayStatus(questionId, '1');
// voiceStart(voice);
voiceContinue();
} else if (playStatus === '1') {
setPlayStatus(questionId, '2');
voicePause();
}
};
const clickChecked = () => {
if (!needCheck) {
return;
}
setChecked(questionId, !checked);
};
return (
<div className={styles.stepQuestionItem}>
<TouchOpacity onClick={playOrPause}>
<img
src={getPlayIcon()}
alt="play"
className={needPlay && playStatus !== '0' ? styles.leftIcon : styles.hide}
></img>
</TouchOpacity>
<div className={styles.itemText}>{text}</div>
<TouchOpacity onClick={clickChecked}>
<img src={getCheckIcon()} alt="check" className={styles.rightIcon}></img>
</TouchOpacity>
</div>
);
}
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import styles from './DoubleRecord.module.scss'; import styles from './DoubleRecord.module.scss';
import Logo from '../assets/img/aia-logo.jpg'; import TouchOpacity from 'components/TouchOpacity';
import IconHome from '../assets/img/home.png';
import TouchOpacity from '../components/TouchOpacity'; import Logo from 'assets/img/aia-logo.jpg';
import IconHome from 'assets/img/home.png';
import IconPosition from 'assets/img/position.png';
import IconPositionSelected from 'assets/img/position-selected.png';
import QuestionItem from './DoubleRecord.components/QuestionItem';
// 调用app的展示PDF方法,合同展示节点使用
const showPDF = () => {
if (!window.webkit) {
alert('window.webkit 未定义');
return;
}
window.webkit.messageHandlers.aiaPDFPreView.postMessage({
pdfPath: 'https://marsandheart.github.io/pdf/frontendKnowledge.pdf',
pdfName: '免除保险人责任条款'
});
};
// question不一定都是问题,也可能是答案,其实分为需要读/不需要读 和 需要操作/不需要操作
const defaultSteps = [
{
id: 1,
label: '节点一',
titleText: '开场',
questions: [
{
questionId: '1',
needPlay: true,
needCheck: false,
playStatus: '0', // 0 未开始;1 播放中;2 暂停中; 3 已结束
checked: false,
text: (
<span>
<span className={styles.seller}>销售人员:</span>
根据银保监会有关规定,接下来我将以录音录像的方式对本次销售过程关键环节予以记录,请问您是否同意?
</span>
),
voice:
'根据银保监会有关规定,接下来我将以录音录像的方式对本次销售过程关键环节予以记录,请问您是否同意?'
},
{
questionId: '2',
needPlay: false,
needCheck: true,
playStatus: '0',
checked: false,
text: (
<span>
<span className={styles.buyer}>投保人:</span>
同意。
</span>
),
voice: '同意。'
},
{
questionId: '3',
needPlay: true,
needCheck: false,
playStatus: '0',
checked: false,
text: (
<span>
<span className={styles.seller}>销售人员:</span>
张三先生,您好,我是友邦保险上海分公司的销售人员02293049423。
</span>
),
voice: '张三先生,您好,我是友邦保险上海分公司的销售人员02293049423。'
},
{
questionId: '4',
needPlay: true,
needCheck: false,
playStatus: '0',
checked: false,
text: <span>请销售人员对镜头出示展业证,在镜头上展示3秒,保证对焦准确,画质清晰。</span>,
voice: '请销售人员对镜头出示展业证,在镜头上展示3秒,保证对焦准确,画质清晰。'
},
{
questionId: '5',
needPlay: true,
needCheck: false,
playStatus: '0',
checked: false,
text: (
<span>
<span className={styles.seller}>销售人员:</span>
张三先生,为规范保险销售从业人员的销售行为,也为了更好地保护您的合法权益,请出示您的身份证件,在镜头上展示3秒,保证对焦准确,画质清晰。
</span>
),
voice:
' 张三先生,为规范保险销售从业人员的销售行为,也为了更好地保护您的合法权益,请出示您的身份证件,在镜头上展示3秒,保证对焦准确,画质清晰。'
}
]
},
{
id: 2,
label: '节点二',
titleText: '告知声明',
questions: [
{
questionId: '',
text: '',
voice: ''
}
]
},
{
id: 3,
label: '节点三',
titleText: '确认购买产品关键要素及风险提示(第一部分:投保信息真实性及犹豫期)',
questions: [
{
questionId: '',
text: '',
voice: ''
}
]
},
{
id: 4,
label: '节点四',
titleText: '确认购买产品关键要素及风险提示(第二部分:产品类型及缴费方式)',
questions: [
{
questionId: '',
text: '',
voice: ''
}
]
},
{
id: 5,
label: '节点五',
titleText: '确认购买产品关键要素及风险提示(保险责任、利益不确定性及观察期)',
questions: [
{
questionId: '',
text: '',
voice: ''
}
]
},
{
id: 6,
label: '节点六',
titleText:
'确认购买产品关键要素及风险提示(人身保险投保提示书、计划建议书、免责条款书面说明、风险提示及签字)',
questions: [
{
questionId: '1',
text: (
<span>
请销售人员点击链接向镜头展示
<span className={styles.extlink} onClick={showPDF}>
《免除保险人责任条款》
</span>
至少3秒,保证标题清晰后给投保人阅读
</span>
),
voice: ''
}
]
},
{
id: 7,
label: '节点七',
titleText: '签字确认',
questions: [
{
questionId: '1',
needPlay: true,
needCheck: false,
playStatus: '0',
checked: false,
text:
'刚才已请投保人阅读过投保提示书、免除保险人责任条款、保险条款及保险合同内容变更申请书,在确保镜头可以录制客户签字过程情况下,请投保人张三签字确认。',
voice:
'刚才已请投保人阅读过投保提示书、免除保险人责任条款、保险条款及保险合同内容变更申请书,在确保镜头可以录制客户签字过程情况下,请投保人张三签字确认。'
}
]
}
];
export default function(props) { export default function(props) {
const [steps, updateSteps] = useState(defaultSteps);
const [imgSrc, setImgSrc] = useState(''); const [imgSrc, setImgSrc] = useState('');
const [stepId, setStepId] = useState(1);
const [questionId, setQuestionId] = useState('1');
// const [signVisible, setSignVisible] = useState(false);
const currentStep = steps.find((s) => s.id === stepId);
useEffect(() => {
console.log('use effect');
setTimeout(() => {
playQuestion(questionId);
}, 1000);
}, [questionId]);
// 朗读当前问题
const playQuestion = (questionId) => {
const targetQuestion = currentStep.questions.find((q) => q.questionId === questionId);
if (!targetQuestion.needPlay) {
return;
}
setPlayStatus(questionId, '1');
voiceStart(targetQuestion.voice);
};
// 设置问题的播放状态,以展示不同的图标
const setPlayStatus = (qId, playStatus) => {
const newSteps = steps.map((stp) => ({
...stp,
questions: stp.questions.map((qst) => ({
...qst
}))
}));
const stepIdx = newSteps.findIndex((s) => s.id === stepId);
const questionIdx = currentStep.questions.findIndex((q) => q.questionId === qId);
if (stepIdx === -1 || questionIdx === -1) {
console.log('error question');
return;
}
newSteps[stepIdx].questions[questionIdx].playStatus = playStatus;
updateSteps(newSteps);
console.log(`设置问题${qId}${playStatus}`);
};
// 勾选,用于需要勾选的问题
const setChecked = (qId, checked) => {
const newSteps = steps.map((stp) => ({
...stp,
questions: stp.questions.map((qst) => ({
...qst
}))
}));
const stepIdx = newSteps.findIndex((s) => s.id === stepId);
const questionIdx = currentStep.questions.findIndex((q) => q.questionId === qId);
if (stepIdx === -1 || questionIdx === -1) {
console.log('error question');
return;
}
newSteps[stepIdx].questions[questionIdx].checked = checked;
updateSteps(newSteps);
console.log(checked);
};
const setCheckThenNextQuestion = () => {
setChecked(questionId, true);
goNextQuestion();
};
const setPlayStatusAndChecked = (qId, playStatus, checked) => {
const newSteps = steps.map((stp) => ({
...stp,
questions: stp.questions.map((qst) => ({
...qst
}))
}));
const stepIdx = newSteps.findIndex((s) => s.id === stepId);
const questionIdx = currentStep.questions.findIndex((q) => q.questionId === qId);
if (stepIdx === -1 || questionIdx === -1) {
console.log('error question');
return;
}
newSteps[stepIdx].questions[questionIdx].playStatus = playStatus;
newSteps[stepIdx].questions[questionIdx].checked = checked;
updateSteps(newSteps);
console.log(checked);
};
// app结束朗读后调用
const finishOneVoice = () => {
const targetQuestion = currentStep.questions.find((q) => q.questionId === questionId);
if (targetQuestion.needCheck) {
// stop and wait check
setPlayStatus(questionId, '3');
console.log('need you check');
return;
} else {
console.log('auto check');
// setPlayStatus(questionId,'3');
// checkCurrentQuestion();
setPlayStatusAndChecked(questionId, '3', true);
goNextQuestion();
}
};
// 当前问题设置为已确认
// const checkCurrentQuestion = () => {
// const newSteps = steps.map((stp) => ({
// ...stp,
// questions: stp.questions.map((qst) => ({
// ...qst
// }))
// }));
// const stepIdx = newSteps.findIndex((s) => s.id === stepId);
// const questionIdx = currentStep.questions.findIndex((q) => q.questionId === questionId);
// if (stepIdx === -1 || questionIdx === -1 ) {
// console.log('error question');
// return;
// }
// newSteps[stepIdx].questions[questionIdx].checked = true;
// updateSteps(newSteps);
// console.log('checked');
// }
// 下一个问题
const goNextQuestion = () => {
const newSteps = steps.map((stp) => ({
...stp,
questions: stp.questions.map((qst) => ({
...qst
}))
}));
const stepIdx = newSteps.findIndex((s) => s.id === stepId);
const questionIdx = currentStep.questions.findIndex((q) => q.questionId === questionId);
if (questionIdx === currentStep.questions.length - 1) {
console.log('this is the last question');
return;
}
if (stepIdx === -1 || questionIdx === -1) {
console.log('error question');
return;
}
const nextQuestionId = newSteps[stepIdx].questions[questionIdx + 1].questionId;
setQuestionId(nextQuestionId); // 设置完之后触发useEffect,由useEffect调用app的朗读
};
// 调用app的语音播报,监听语音结束,在刚进入页面时自动调用一次,每一个问题结束后判断是否自动调用
const voiceStart = (voiceContent) => {
// alert(`播放: ${voiceContent}`);
// setTimeout(() => {
// console.log('finish one voice');
// finishOneVoice();
// }, 3000);
if (!window.webkit) {
alert('window.webkit 未定义');
return;
}
window.webkit.messageHandlers.aiaVoiceBroadCastContent.postMessage({ content: voiceContent });
window.aiaVoiceFinish = () => {
console.log('finish one step');
finishOneVoice();
};
};
// 调用app的语音暂停,点击问题的暂停按钮时候调用
const voicePause = () => {
// alert('暂停播放');
if (!window.webkit) {
alert('window.webkit 未定义');
return;
}
window.webkit.messageHandlers.aiaVoiceBroadPause.postMessage({});
};
// 调用app的暂停后继续播放方法
const voiceContinue = () => {
// alert('继续播放');
if (!window.webkit) {
alert('window.webkit 未定义');
return;
}
window.webkit.messageHandlers.aiaVoiceBroadContinuePlay.postMessage({});
};
const showPDF = () => { // 调用app的语音停止,在跳转、翻页的时候调用,避免翻页后继续播放
if (!window.aiaPDFPreView) { const voiceStop = () => {
alert('window.aiaPDFPreView is not a function'); // alert('停止播放');
if (!window.webkit) {
alert('window.webkit 未定义');
return; return;
} }
window.aiaPDFPreView('https://marsandheart.github.io/pdf/frontendKnowledge.pdf'); window.webkit.messageHandlers.aiaVoiceBroadStop.postMessage({});
}; };
// 调用app的签名方法,展示签名组件,签名节点使用
const showSign = () => { const showSign = () => {
if (!window.aiaShowSignView) { if (!window.webkit) {
alert('window.aiaShowSignView is not a function'); alert('window.webkit 未定义');
return; return;
} }
window.aiaShowSignView(); window.webkit.messageHandlers.aiaShowSignView.postMessage({});
window.aiaGetSignImage = (imgData) => { // window.aiaShowSignView();
const obj = { window.aiaGetSignImage = (base64Data) => {
method: 'aiaGetSignImage', const decodeBase64 = decodeURIComponent(base64Data);
param: imgData const base64Src = 'data:image/png;base64,' + decodeBase64;
setImgSrc(base64Src);
}; };
setImgSrc(imgData);
alert(JSON.stringify(obj));
}; };
// 测试用,在图片获取后查看图片src
const showImgSrc = () => {
alert(
JSON.stringify({
imgSrc
})
);
};
// 上一个节点,如果是第一节点则回到上一页
const lastStep = () => {
if (stepId === 1) {
window.history.go(-1);
} else {
setStepId(stepId - 1);
setQuestionId('1');
}
};
// 下一个节点,如果是最后节点则前往保户服务页面
const nextStep = () => {
setPlayStatus(questionId, '3');
voiceStop();
if (stepId === 7) {
// setSignVisible(true);
return;
} else {
setStepId(stepId + 1);
setQuestionId('1');
}
}; };
return ( return (
...@@ -43,7 +459,7 @@ export default function(props) { ...@@ -43,7 +459,7 @@ export default function(props) {
<img src={IconHome} alt="logo"></img> <img src={IconHome} alt="logo"></img>
</div> </div>
</div> </div>
<div className={styles.main}> {/* <div className={styles.main}>
<TouchOpacity className={styles.btn} onClick={showPDF}> <TouchOpacity className={styles.btn} onClick={showPDF}>
PDF预览 PDF预览
</TouchOpacity> </TouchOpacity>
...@@ -52,17 +468,77 @@ export default function(props) { ...@@ -52,17 +468,77 @@ export default function(props) {
</TouchOpacity> </TouchOpacity>
<div style={{ clear: 'both' }}></div> <div style={{ clear: 'both' }}></div>
<div>签名图片展示:</div> <div>签名图片展示:</div>
<div> <div onClick={showImgSrc}>
<img alt="签名图片" src={imgSrc}></img> <img alt="签名图片" src={imgSrc}></img>
</div> </div>
</div>
{/* <div className={styles.main}>
<div className={styles.stepArea}>steps</div>
<div className={styles.questionArea}>questions</div>
</div> */} </div> */}
<div className={styles.main}>
<div className={styles.stepArea}>
{steps.map((item) => (
<TouchOpacity
key={item.id}
className={stepId === item.id ? styles.stepIndexSelected : styles.stepIndex}
onClick={() => {
setStepId(item.id);
}}
>
<img
src={stepId === item.id ? IconPositionSelected : IconPosition}
alt="icon-position"
></img>
<span>{item.label}</span>
</TouchOpacity>
))}
</div>
<div className={styles.questionArea}>
<div className={styles.stepTitle}>{currentStep.titleText}</div>
<div className={styles.stepQuestions}>
{currentStep.questions.map((q) => (
<QuestionItem
key={q.questionId}
question={q}
setPlayStatus={setPlayStatus}
setChecked={setCheckThenNextQuestion}
voiceStart={voiceStart}
voicePause={voicePause}
voiceContinue={voiceContinue}
/>
))}
{/* {currentStep.questions.map(q=>(
<div className={styles.stepQuestionItem}>
<TouchOpacity>
<img src={IconPosition} alt="play" className={styles.leftIcon}></img>
</TouchOpacity>
<div className={styles.itemText}>
{q.text}
</div>
<TouchOpacity>
<img src={IconPosition} alt="check" className={styles.rightIcon}></img>
</TouchOpacity>
</div>
))} */}
{stepId === 7 && (
<>
<TouchOpacity className={styles.btn} onClick={showSign}>
呼出签名视图
</TouchOpacity>
<div style={{ clear: 'both' }}></div>
<div>签名图片展示:</div>
<div onClick={showImgSrc}>
<img alt="签名图片" src={imgSrc}></img>
</div>
</>
)}
</div>
</div>
</div>
<div className={styles.footer}> <div className={styles.footer}>
<div className={styles.footerBtn}>上一步</div> <TouchOpacity className={styles.footerBtn} onClick={lastStep}>
<div className={styles.footerBtn}>下一步</div> 上一步
</TouchOpacity>
<TouchOpacity className={styles.footerBtn} onClick={nextStep}>
下一步
</TouchOpacity>
</div> </div>
</div> </div>
); );
......
@import '../assets/css/common.scss'; @import 'assets/css/common.scss';
.page{ .page{
width: 100vw; width: 100vw;
...@@ -6,27 +6,30 @@ ...@@ -6,27 +6,30 @@
background-color: #E2E1E6; background-color: #E2E1E6;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
font-size: 0.14rem;
} }
.header{ .header{
height: 60px; padding-top: 0.2rem;
height: 0.7rem;
background-color: $primaryColor; background-color: $primaryColor;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
color: white; color: white;
font-size: 22px; font-size: 0.24rem;
font-weight: 300;
.aiaLogo{ .aiaLogo{
width: 120px; width: 1.2rem;
} }
.homeIcon{ .homeIcon{
width: 120px; width: 1.2rem;
margin-right: 20px; margin-right: 0.2rem;
img{ img{
width: 20px; width: 0.2rem;
height: 20px; height: 0.2rem;
float: right; float: right;
} }
} }
...@@ -35,21 +38,70 @@ ...@@ -35,21 +38,70 @@
.main{ .main{
height: 80%; height: 80%;
padding: 10px 20px; padding: 0.24rem 0.2rem;
.stepArea{ .stepArea{
height: 10%; height: 10%;
width: 100%;
display: flex;
justify-content: space-between;
align-items: flex-end;
padding-left: 5%;
padding-right: 5%;
.stepIndex{
user-select:none;
background-color: #ECE9EC;
font-size: 0.16rem;
color: #999999;
padding: 0.1rem 0.2rem;
border-top: 3px solid #bcbcbc;
border-radius: 3px;
img{
width:0.24rem;
height:0.24rem;
margin-right: 0.05rem;
}
}
.stepIndexSelected{
@extend .stepIndex;
color: $primaryColor;
border-top: 3px solid $primaryColor;
}
} }
.questionArea { .questionArea {
height: 90%; height: 90%;
border: 1px solid #333333; border: 1px solid #999999;
border-radius: 5px; border-radius: 10px;
padding: 0.15rem 0.3rem;
background-color: #ECE9EC;
.stepTitle{
font-size: 0.25rem;
font-weight: bold;
}
.stepQuestions{
margin-top: 0.3rem;
overflow-x: hidden;
overflow-y: scroll;
height: 88%;
} }
}
}
.seller{
color: #4A45C4;
}
.buyer{
color: $primaryColor;
}
.extlink{
color: #D37841;
} }
.btn{ .btn{
user-select:none; user-select:none;
background: #CE1F57; background: $primaryColor;
min-width:10vw; min-width:10vw;
height:5vh; height:5vh;
line-height: 3.5vh; line-height: 3.5vh;
...@@ -62,13 +114,14 @@ ...@@ -62,13 +114,14 @@
} }
.footer{ .footer{
height: 50px; height: 0.5rem;
padding: 10px 20px; padding: 0.1rem 0.2rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.footerBtn{ .footerBtn{
user-select:none;
width: 49%; width: 49%;
height: 40px; height: 0.4rem;
background-color: $primaryColor; background-color: $primaryColor;
color: white; color: white;
display: flex; display: flex;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment