lion 2 months ago
parent 7bf7060395
commit 152ef5ca04

@ -57,4 +57,3 @@ export function destroy(params) {
}

@ -56,5 +56,11 @@ export function destroy(params) {
})
}
export function qrCode(params) {
return request({
method: "get",
url: "/api/admin/courses/evaluation-qrcode",
params
})
}

@ -470,7 +470,7 @@ export default {
changeIntroduce(e) {
console.log("e", e);
if (e) {
this.form.title = this.form.title + " | " + e;
this.form.title = this.form.title + " - " + e;
}
},
changeCourse(e) {
@ -485,7 +485,7 @@ export default {
this.course_options.map((item) => {
if (item.id === e) {
this.form.title =
(item.type_detail ? item.type_detail.name + " | " : "") +
(item.type_detail ? item.type_detail.name + " - " : "") +
item.name;
this.form.start_time = item.start_date
? item.start_date + " 00:00:00"
@ -518,12 +518,12 @@ export default {
//
let cleanTitle = this.form.title;
this.module_options.forEach(module => {
if (cleanTitle.includes(' | ' + module.value)) {
cleanTitle = cleanTitle.replace(' | ' + module.value, '');
if (cleanTitle.includes(' - ' + module.value)) {
cleanTitle = cleanTitle.replace(' - ' + module.value, '');
}
});
//
this.form.title = cleanTitle + ' | ' + value;
this.form.title = cleanTitle + ' - ' + value;
}
},
onCreateModule(value) {
@ -553,7 +553,7 @@ export default {
if (this.type == "add") {
this.form.id = "";
this.form.title = this.form.introduce
? this.form.title + " | " + this.form.introduce
? this.form.title + " - " + this.form.introduce
: this.form.title;
}
save({

@ -16,8 +16,8 @@
</div>
<div class="course-list-select">
<el-radio-group v-model="is_arrange" @change="changeIsArrange">
<el-radio :label="1">排课</el-radio>
<el-radio :label="0">排课</el-radio>
<el-radio :label="1">排课</el-radio>
<el-radio :label="0">无需排课</el-radio>
</el-radio-group>
</div>
<div class="course-list-select">

@ -59,6 +59,20 @@
</div>
</div>
</template>
<template v-slot:is_yh_invested>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>是否被投企业
</div>
<div class="xy-table-item-content">
<el-select v-model="form.is_yh_invested" placeholder="请选择是否被投企业" clearable style="width: 100%;">
<el-option v-for="(item,index) in [{label:'否',value:0},{label:'是',value:1}]" :key="index" :label="item.label" :value="item.value">
</el-option>
</el-select>
</div>
</div>
</template>
<template v-slot:company_scale>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold">
@ -195,6 +209,7 @@
company_name: '',
company_attribute: '',
tag: '',
is_yh_invested: '',
company_scale: '',
company_date: '',
company_legal_representative: '',
@ -253,6 +268,7 @@
id: this.id,
}).then(res => {
this.form = this.base.requestToForm(res, this.form)
this.form.is_yh_invested = this.form.is_yh_invested ? 1 : 0
})
},
async searchCompany(query) {
@ -312,6 +328,7 @@
company_name: '',
company_attribute: '',
tag: '',
is_yh_invested: '',
company_scale: '',
company_date: '',
company_legal_representative: '',

@ -67,8 +67,11 @@
<template v-slot:tag>
<el-table-column align='center' label="集团标签" width="120" header-align="center">
<template slot-scope="scope">
<div v-if="scope.row.is_yh_invested" style="margin:3px">
<el-tag type="danger">被投企业</el-tag>
</div>
<div v-for="item in formSelect.company_tag">
<el-tag v-if="item.value===scope.row.tag"
<el-tag v-if="item.value===scope.row.tag" style="margin:3px"
:type="item.remark?item.remark:''">{{scope.row.tag}}</el-tag>
</div>
</template>
@ -164,7 +167,7 @@
prop: 'company_attribute',
label: '企业资质',
align: 'center',
width: 120
width: 180
}, {
prop: 'tag',
label: '集团标签',

@ -1,10 +1,44 @@
<template>
<el-dialog :visible.sync="visible" width="60%" :show-close="false" class="survey-dialog-mobile">
<el-dialog :visible.sync="visible" width="80%" :show-close="false" class="survey-dialog-mobile">
<div class="survey-mobile-bg">
<div class="survey-mobile-card">
<div class="survey-header">
<div class="survey-title">{{ surveyData.title }}</div>
<div class="survey-description">{{ surveyData.desc }}</div>
<!-- 预览模式下显示二维码 -->
<div v-if="previewOnly && surveyData.qrCodeData" class="qr-code-section">
<div class="qr-code-title">
<i class="el-icon-qrcode"></i> 问卷二维码
</div>
<div class="qr-code-container">
<img
:src="surveyData.qrCodeData"
alt="问卷二维码"
class="qr-code-image"
@error="handleQrCodeError"
/>
<div class="qr-code-actions">
<el-button
type="primary"
size="mini"
@click="downloadQrCode"
icon="el-icon-download"
>
下载二维码
</el-button>
<!-- <el-button
type="info"
size="mini"
@click="copyQrCodeUrl"
icon="el-icon-copy-document"
>
复制链接
</el-button> -->
</div>
</div>
</div>
<div class="survey-meta">
<span class="meta-item"><i class="el-icon-date"></i> {{ surveyData.start_time }}</span>
<span class="meta-item"><i class="el-icon-time"></i> {{ surveyData.end_time }}</span>
@ -14,8 +48,16 @@
<div v-for="(q, idx) in questionList" :key="q.id" class="question-item">
<div class="question-header">
<span class="question-number">{{ idx+1 }}</span>
<span v-if="q.rule && q.rule.includes('required')" class="required-mark">*</span>
<span class="question-title">{{ q.name }}</span>
<div class="question-title">
<div class="question-title-text">
<span v-if="q.rule && q.rule.includes('required')" class="required-mark">*</span>
<span class="question-title">{{ q.name }}</span>
</div>
<div class="question-title-desc" v-if="q.course_content">
<span class="question-title-desc-text">{{ q.course_content?q.course_content.theme:'' }}{{ q.course_content.teacher?' -- '+q.course_content.teacher.name:'' }}</span>
</div>
</div>
</div>
<div class="question-content">
@ -122,6 +164,7 @@
page_size: 999,
sort_name: 'sort',
sort_type: 'ASC',
show_relation:['courseContent.teacher'],
filter: [{
key: 'course_content_evaluation_id',
op: 'eq',
@ -130,13 +173,82 @@
})
this.questionList = res.data
},
//
downloadQrCode() {
if (!this.surveyData.qrCodeData) {
this.$message.warning('二维码数据不存在');
return;
}
try {
const link = document.createElement('a');
link.href = this.surveyData.qrCodeData;
link.download = `${this.surveyData.title}-问卷二维码.png`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
this.$message.success('二维码下载成功');
} catch (error) {
console.error('下载失败:', error);
this.$message.error('下载失败,请重试');
}
},
//
copyQrCodeUrl() {
const surveyUrl = `${window.location.origin}/survey-fill.html?id=${this.surveyData.id}`;
if (navigator.clipboard) {
navigator.clipboard.writeText(surveyUrl).then(() => {
this.$message.success('问卷链接已复制到剪贴板');
}).catch(() => {
this.fallbackCopyTextToClipboard(surveyUrl);
});
} else {
this.fallbackCopyTextToClipboard(surveyUrl);
}
},
//
fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.left = '-999999px';
textArea.style.top = '-999999px';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
this.$message.success('问卷链接已复制到剪贴板');
} catch (err) {
console.error('复制失败:', err);
this.$message.error('复制失败,请手动复制');
}
document.body.removeChild(textArea);
},
//
handleQrCodeError() {
console.error('二维码图片加载失败');
this.$message.warning('二维码图片加载失败');
}
}
}
</script>
<style scoped>
.survey-dialog-mobile>>>.el-dialog{
margin-top:5vh!important;
}
.survey-dialog-mobile>>>.el-dialog__body {
padding: 0;
background: #f4f6fa;
height:80vh;
overflow-y: scroll;
}
.survey-mobile-bg {
@ -149,7 +261,7 @@
.survey-mobile-card {
width: 100vw;
max-width: 414px;
max-width: 600px;
min-width: 320px;
background: #fff;
border-radius: 18px;
@ -213,7 +325,7 @@
}
.question-number {
background: #3498db;
background: #bf976e;
color: #fff;
width: 22px;
height: 22px;
@ -229,10 +341,15 @@
.question-title {
font-size: 15px;
font-weight: 600;
color: #2c3e50;
color: #333;
line-height: 1.4;
flex: 1;
}
.question-title-desc-text{
font-size: 12px;
color: #6c757d;
line-height: 1.6;
}
.required-mark {
color: #e74c3c;
margin-left: 4px;
@ -298,6 +415,58 @@
margin-bottom: 10px;
}
/* 二维码相关样式 */
.qr-code-section {
margin: 20px 0;
padding: 20px;
background: #f8f9fa;
border-radius: 12px;
border: 1px solid #e9ecef;
}
.qr-code-title {
font-size: 16px;
font-weight: 600;
color: #2c3e50;
margin-bottom: 15px;
text-align: center;
}
.qr-code-title i {
margin-right: 8px;
color: #3498db;
}
.qr-code-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 15px;
}
.qr-code-image {
width: 150px;
height: 150px;
border: 2px solid #e9ecef;
border-radius: 8px;
background: #fff;
padding: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.qr-code-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
justify-content: center;
}
.qr-code-actions .el-button {
border-radius: 20px;
font-size: 13px;
padding: 8px 16px;
}
@media (max-width: 500px) {
.survey-mobile-card {
max-width: 100vw;

@ -27,15 +27,33 @@
>
<div class="course-schedule-selection">
<div class="schedule-list">
<el-radio
<div
v-for="schedule in selectedCourseSchedules"
:key="schedule.id"
v-model="selectedScheduleId"
:label="schedule.id"
class="schedule-item"
:class="{ 'selected': selectedScheduleId === schedule.id }"
@click="toggleScheduleSelection(schedule.id)"
>
{{ schedule.date }} {{ schedule.period }} | {{ schedule.theme }}
</el-radio>
<div class="schedule-radio">
<i
:class="selectedScheduleId === schedule.id ? 'el-icon-check' : 'el-icon-circle-outline'"
></i>
</div>
<div class="schedule-content">
{{ schedule.date }} {{ schedule.period }} | {{ schedule.theme }}
</div>
</div>
</div>
<!-- 添加取消选择按钮 -->
<div v-if="selectedScheduleId" class="deselect-section">
<el-button
type="info"
size="mini"
@click="deselectSchedule"
icon="el-icon-close"
>
取消选择
</el-button>
</div>
</div>
</el-form-item>
@ -189,6 +207,26 @@
},
// -
handleScheduleChange(value) {
if (value === null) {
this.selectedScheduleId = null;
}
},
//
toggleScheduleSelection(scheduleId) {
if (this.selectedScheduleId === scheduleId) {
//
this.selectedScheduleId = null;
} else {
//
this.selectedScheduleId = scheduleId;
}
},
deselectSchedule() {
this.selectedScheduleId = null;
},
saveField() {
console.log("this.selectedForm.select_item",this.selectedForm)
@ -385,5 +423,41 @@
.schedule-item {
padding: 8px 0;
box-sizing: border-box;
display: flex;
align-items: center;
cursor: pointer;
padding: 8px 12px;
border-radius: 4px;
transition: all 0.2s ease;
margin-bottom: 4px;
&:hover {
background-color: #f5f7fa;
}
&.selected {
background-color: #e1f3d8;
border-radius: 4px;
padding: 8px 12px;
box-sizing: border-box;
}
.schedule-radio {
margin-right: 10px;
flex-shrink: 0;
color: #409eff;
font-size: 16px;
}
.schedule-content {
flex-grow: 1;
font-size: 14px;
color: #606266;
}
}
.deselect-section {
margin-top: 10px;
text-align: right;
}
</style>

@ -147,9 +147,9 @@
type="primary"
size="mini"
@click="previewSurvey(survey)"
><i class="el-icon-view"></i> 预览</el-button
><i class="el-icon-view"></i> 预览并生成二维码</el-button
>
<!-- <el-button type="info" size="mini" @click="shareSurvey(survey.id)"><i class="el-icon-share"></i> 分享</el-button> -->
<!-- <el-button type="info" size="mini" @click="shareSurvey(survey.id)"><i class="el-icon-share"></i> 生成二维码</el-button> -->
<!-- <el-button v-if="survey.responses>0" type="success" size="mini" @click="exportData(survey.id)"><i class="el-icon-download"></i> </el-button> -->
</div>
</div>
@ -197,7 +197,8 @@ import SurveyCreateWizard from "./components/SurveyCreateWizard.vue";
import SurveyResultsDialog from "./components/SurveyResultsDialog.vue";
import SurveyFillDialog from "./components/SurveyFillDialog.vue";
import { index as courseApi } from "@/api/course/index.js";
import { index, destroy, save } from "@/api/survey/evaluations.js";
import { index, destroy, save, qrCode} from "@/api/survey/evaluations.js";
export default {
components: {
@ -329,10 +330,29 @@ export default {
};
this.resultsDialogVisible = true;
},
previewSurvey(survey) {
this.fillSurveyData = survey;
this.fillPreviewOnly = true;
this.fillDialogVisible = true;
async previewSurvey(survey) {
try {
//
const qrRes = await qrCode({
id: survey.id
});
//
this.fillSurveyData = {
...survey,
qrCodeData: qrRes.msg || qrRes.data || qrRes
};
this.fillPreviewOnly = true;
this.fillDialogVisible = true;
} catch (error) {
console.error('生成二维码失败:', error);
this.$message.error('生成二维码失败,请重试');
// 使
this.fillSurveyData = survey;
this.fillPreviewOnly = true;
this.fillDialogVisible = true;
}
},
onFillSubmit(answers) {
this.$message.success("提交成功!(模拟)");

Loading…
Cancel
Save