| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- <!-- 顶部导航栏 -->
- <div class="survey-header">
- <div class="header-content">
- @if(!currentContact?.id){
- <button class="back-button" (click)="goBack()">
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M244 400L100 256l144-144M120 256h292"/>
- </svg>
- </button>
- }
- <h1 class="header-title">项目需求调查</h1>
- <div class="header-spacer"></div>
- </div>
- </div>
- <!-- 主内容区 -->
- <div class="survey-container">
- <!-- 加载状态 -->
- @if (loading) {
- <div class="status-view loading-view">
- <div class="spinner">
- <div class="spinner-circle"></div>
- </div>
- <p class="status-text">加载中...</p>
- </div>
- }
- <!-- 错误状态 -->
- @if (error && !loading && !surveyLog?.get('isCompleted')) {
- <div class="status-view error-view">
- <div class="error-icon-wrapper">
- <svg class="icon error-icon" viewBox="0 0 512 512">
- @if (isCustomerOnly) {
- <!-- 仅限客户图标 -->
- <path fill="currentColor" d="M336 256c-20.56 0-40.44-9.18-56-25.84-15.13-16.25-24.37-37.92-26-61-1.74-24.62 5.77-47.26 21.14-63.76S312 80 336 80c23.83 0 45.38 9.06 60.7 25.52 15.47 16.62 23 39.22 21.26 63.63-1.67 23.11-10.9 44.77-26 61C376.44 246.82 356.57 256 336 256zm66-88c0-51.18-42.82-92-94-92s-94 40.82-94 92 42.82 92 94 92 94-40.82 94-92z" opacity=".3"/>
- <path fill="currentColor" d="M336 256c-20.56 0-40.44-9.18-56-25.84-15.13-16.25-24.37-37.92-26-61-1.74-24.62 5.77-47.26 21.14-63.76S312 80 336 80c23.83 0 45.38 9.06 60.7 25.52 15.47 16.62 23 39.22 21.26 63.63-1.67 23.11-10.9 44.77-26 61C376.44 246.82 356.57 256 336 256zM467.83 432H204.18a27.71 27.71 0 01-22-10.67 30.22 30.22 0 01-5.26-25.79c8.42-33.81 29.28-61.85 60.32-81.08C264.79 297.4 299.86 288 336 288c36.85 0 71 9.23 98.83 26.73 31.45 19.86 52.3 48 60.38 81.55a30.27 30.27 0 01-5.32 25.78A27.68 27.68 0 01467.83 432z"/>
- } @else {
- <!-- 常规错误图标 -->
- <path fill="currentColor" d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm0 319.91a20 20 0 1120-20 20 20 0 01-20 20zm21.72-201.15l-5.74 122a16 16 0 01-32 0l-5.74-121.94v-.05a21.74 21.74 0 1143.44 0z"/>
- }
- </svg>
- </div>
- <h2 class="error-title">{{ isCustomerOnly ? '仅限客户填写' : '加载失败' }}</h2>
- <p class="error-message">{{ error }}</p>
- @if (isCustomerOnly) {
- <div class="info-box">
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M256 56C145.72 56 56 145.72 56 256s89.72 200 200 200 200-89.72 200-200S366.28 56 256 56zm0 82a26 26 0 11-26 26 26 26 0 0126-26zm48 226h-88a16 16 0 010-32h28v-88h-16a16 16 0 010-32h32a16 16 0 0116 16v104h28a16 16 0 010 32z"/>
- </svg>
- <div class="info-text">
- <p class="info-title">客户填写入口</p>
- <p class="info-desc">请通过企微群聊中收到的问卷链接进入</p>
- </div>
- </div>
- }
- <button class="btn-primary" (click)="goBack()">返回</button>
- </div>
- }
- <!-- 欢迎页 -->
- @if (currentState === 'welcome' && !loading && !error) {
- <div class="welcome-view">
- <!-- 用户信息卡片 -->
- <div class="user-card">
- <div class="user-avatar">
- <img [src]="currentContact?.get('data')?.avatar || 'assets/default-avatar.png'" alt="头像" />
- </div>
- <h2 class="user-greeting">您好, {{ currentContact?.get('realname') || currentContact?.get('name') }}</h2>
- <p class="user-subtitle">欢迎参与需求调查</p>
- </div>
- <!-- 问卷介绍 -->
- <div class="intro-card">
- <div class="intro-header">
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M336 64h32a48 48 0 0148 48v320a48 48 0 01-48 48H144a48 48 0 01-48-48V112a48 48 0 0148-48h32" opacity=".3"/>
- <path fill="currentColor" d="M336 64h-80a48 48 0 00-96 0h-80a48 48 0 00-48 48v320a48 48 0 0048 48h224a48 48 0 0048-48V112a48 48 0 00-48-48zM256 32a16 16 0 11-16 16 16 16 0 0116-16zm112 400H144V112h224z"/>
- </svg>
- <h3>家装效果图服务需求调查</h3>
- </div>
- <div class="intro-body">
- <p class="intro-text">
- 尊敬的伙伴,为让本次效果图服务更贴合您的工作节奏与核心需求,我们准备了简短选择式问卷。
- </p>
- <p class="intro-text">
- 您的偏好将直接帮我们校准服务方向,感谢支持!
- </p>
- </div>
- <!-- 问卷信息标签 -->
- <div class="info-tags">
- <div class="info-tag">
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm61.8-104.4l-84.9-61.7c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v141.7l66.8 48.6c5.4 3.9 6.5 11.4 2.6 16.8L334.6 349c-3.9 5.3-11.4 6.5-16.8 2.6z"/>
- </svg>
- <span>3-5分钟</span>
- </div>
- <div class="info-tag">
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M144 144v296a8 8 0 008 8h56V144zm144 0v304h56a8 8 0 008-8V144zm144 0v272a24 24 0 01-24 24h-40V144zM64 144v328a24 24 0 0024 24h40V144z" opacity=".3"/>
- </svg>
- <span>{{ effectiveQuestions.length }}道题</span>
- </div>
- <div class="info-tag">
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/>
- </svg>
- <span>选择为主</span>
- </div>
- </div>
- </div>
- <!-- 开始按钮 -->
- <button class="btn-start" (click)="startSurvey()">
- <span>开始填写</span>
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M294.1 256L167 129c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.3 34 0L345 239c9.1 9.1 9.3 23.7.7 33.1L201.1 417c-4.7 4.7-10.9 7-17 7s-12.3-2.3-17-7c-9.4-9.4-9.4-24.6 0-33.9l127-127.1z"/>
- </svg>
- </button>
- </div>
- }
- <!-- 答题页 -->
- @if (currentState === 'questionnaire' && !loading && !error) {
- <div class="questionnaire-view">
- <!-- 进度指示器 -->
- <div class="progress-section">
- <div class="progress-bar-wrapper">
- <div class="progress-bar">
- <div class="progress-fill" [style.width.%]="getProgress()"></div>
- </div>
- </div>
- <div class="progress-info">
- <span class="progress-current">{{ currentQuestionIndex + 1 }}</span>
- <span class="progress-separator">/</span>
- <span class="progress-total">{{ effectiveQuestions.length }}</span>
- </div>
- </div>
- @if (getCurrentQuestion(); as question) {
- <!-- 题目卡片 -->
- <div class="question-card">
- <!-- 章节标签 -->
- <div class="section-badge">{{ question.section }}</div>
- <!-- 题目内容 -->
- <div class="question-content">
- <h3 class="question-title">
- <span class="question-number">{{ currentQuestionIndex + 1 }}.</span>
- <span class="question-text">{{ question.title }}</span>
- @if (question.required) {
- <span class="required-star">*</span>
- }
- </h3>
- <!-- 单选题 -->
- @if (question.type === 'single') {
- <div class="options-list">
- @for (option of question.options; track option) {
- <div
- class="option-item"
- [class.selected]="answers[question.id] === option"
- (click)="selectSingleOption(option)">
- <div class="option-radio">
- <div class="radio-outer">
- <div class="radio-inner"></div>
- </div>
- </div>
- <span class="option-label">{{ option }}</span>
- </div>
- }
- @if (question.hasOther) {
- <div
- class="option-item"
- [class.selected]="answers[question.id]?.startsWith('其他')"
- (click)="selectSingleOption('其他')">
- <div class="option-radio">
- <div class="radio-outer">
- <div class="radio-inner"></div>
- </div>
- </div>
- <span class="option-label">其他</span>
- </div>
- }
- </div>
- @if (showOtherInput) {
- <div class="input-wrapper">
- <input
- type="text"
- class="text-input"
- [(ngModel)]="otherInput"
- placeholder="请输入其他内容..."
- autofocus />
- </div>
- }
- }
- <!-- 多选题 -->
- @if (question.type === 'multiple') {
- <div class="options-list">
- @for (option of question.options; track option) {
- <div
- class="option-item"
- [class.selected]="hasMultipleOption(question.id, option)"
- (click)="toggleMultipleOption(option)">
- <div class="option-checkbox">
- <div class="checkbox-box">
- <svg class="icon checkmark" viewBox="0 0 512 512">
- <path fill="currentColor" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/>
- </svg>
- </div>
- </div>
- <span class="option-label">{{ option }}</span>
- </div>
- }
- @if (question.hasOther) {
- <div
- class="option-item"
- [class.selected]="hasMultipleOptionStartsWith(question.id, '其他')"
- (click)="toggleMultipleOption('其他')">
- <div class="option-checkbox">
- <div class="checkbox-box">
- <svg class="icon checkmark" viewBox="0 0 512 512">
- <path fill="currentColor" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"/>
- </svg>
- </div>
- </div>
- <span class="option-label">其他</span>
- </div>
- }
- </div>
- @if (showOtherInput) {
- <div class="input-wrapper">
- <input
- type="text"
- class="text-input"
- [(ngModel)]="otherInput"
- placeholder="请输入其他内容..." />
- </div>
- }
- }
- <!-- 文本题 -->
- @if (question.type === 'text') {
- <div class="input-wrapper">
- <textarea
- class="textarea-input"
- [(ngModel)]="answers[question.id]"
- [placeholder]="question.placeholder || '请输入...'"
- rows="4"></textarea>
- </div>
- }
- <!-- 数字题 -->
- @if (question.type === 'number') {
- <div class="input-wrapper">
- <input
- type="number"
- class="text-input"
- [(ngModel)]="answers[question.id]"
- [placeholder]="question.placeholder || '请输入数字...'" />
- </div>
- }
- </div>
- </div>
- <!-- 导航按钮 -->
- <div class="nav-buttons">
- <button
- class="btn-nav btn-prev"
- [disabled]="currentQuestionIndex === 0"
- (click)="previousQuestion()">
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M217.9 256L345 129c9.4-9.4 9.4-24.6 0-33.9-9.4-9.4-24.6-9.3-34 0L167 239c-9.1 9.1-9.3 23.7-.7 33.1L310.9 417c4.7 4.7 10.9 7 17 7s12.3-2.3 17-7c9.4-9.4 9.4-24.6 0-33.9L217.9 256z"/>
- </svg>
- <span>上一题</span>
- </button>
- <button
- class="btn-nav btn-next"
- (click)="nextQuestion()">
- <span>{{ currentQuestionIndex >= effectiveQuestions.length - 1 ? '提交' : '下一题' }}</span>
- <svg class="icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M294.1 256L167 129c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.3 34 0L345 239c9.1 9.1 9.3 23.7.7 33.1L201.1 417c-4.7 4.7-10.9 7-17 7s-12.3-2.3-17-7c-9.4-9.4-9.4-24.6 0-33.9l127-127.1z"/>
- </svg>
- </button>
- </div>
- }
- </div>
- }
- <!-- 结果页 -->
- @if (currentState === 'result' && !loading && (!error || surveyLog?.get('isCompleted'))) {
- <div class="result-view">
- <!-- 成功图标 -->
- <div class="success-icon-wrapper">
- <svg class="icon success-icon" viewBox="0 0 512 512">
- <path fill="currentColor" d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm108.25 138.29l-134.4 160a16 16 0 01-12 5.71h-.27a16 16 0 01-11.89-5.3l-57.6-64a16 16 0 1123.78-21.4l45.29 50.32 122.59-145.91a16 16 0 0124.5 20.58z"/>
- </svg>
- </div>
- @if(currentContact?.id){
- <h2 class="result-title">问卷提交成功</h2>
- <p class="result-subtitle">感谢您的反馈!</p>
- <p class="result-desc">我们将根据您的选择制定服务方案</p>
- }
-
- <!-- 答卷内容 -->
- <div class="result-card">
- <h3 class="result-card-title">问卷信息</h3>
- <div class="result-list">
- <div class="result-item">
- <div class="result-label">核心服务</div>
- <div class="result-value">{{ getFormattedAnswer('q1') }}</div>
- </div>
- <div class="result-item">
- <div class="result-label">空间数量</div>
- <div class="result-value">{{ getFormattedAnswer('q2') }}</div>
- </div>
- <div class="result-item">
- <div class="result-label">价值侧重</div>
- <div class="result-value">{{ getFormattedAnswer('q3') }}</div>
- </div>
- <div class="result-item">
- <div class="result-label">技术配合</div>
- <div class="result-value">{{ getFormattedAnswer('q4') }}</div>
- </div>
- <div class="result-item">
- <div class="result-label">协作方式</div>
- <div class="result-value">{{ getFormattedAnswer('q5') }}</div>
- </div>
- @if (answers['q6']) {
- <div class="result-item">
- <div class="result-label">注意事项</div>
- <div class="result-value">{{ getFormattedAnswer('q6') }}</div>
- </div>
- }
- @if (answers['q7']) {
- <div class="result-item">
- <div class="result-label">特殊要求</div>
- <div class="result-value">{{ getFormattedAnswer('q7') }}</div>
- </div>
- }
- @if (answers['q8']) {
- <div class="result-item">
- <div class="result-label">参考素材</div>
- <div class="result-value">{{ getFormattedAnswer('q8') }}</div>
- </div>
- }
- </div>
- <div class="result-divider"></div>
- <div class="result-list">
- <div class="result-item">
- <div class="result-label">对接人</div>
- <div class="result-value">{{ answers['contact_name'] || currentContact?.get('realname') || '-' }}</div>
- </div>
- <div class="result-item">
- <div class="result-label">电话</div>
- <div class="result-value">{{ maskPhone(answers['contact_phone'] || currentContact?.get('mobile') || '') }}</div>
- </div>
- </div>
- </div>
- <!-- 返回按钮 -->
- <button class="btn-primary" (click)="goBack()">
- <span>返回项目</span>
- </button>
- </div>
- }
- </div>
|