..
This commit is contained in:
@@ -0,0 +1,589 @@
|
||||
const SatisfactionEvaluate = {
|
||||
template: /*language=HTML*/ `
|
||||
<div class="satisfaction-wrapper" v-show="show">
|
||||
<div class="satisfaction-header">
|
||||
<span class="title">满意度调查</span>
|
||||
<span class="close-btn" @click="show = false">×</span>
|
||||
</div>
|
||||
<div class="satisfaction-content">
|
||||
<form @submit.prevent="onSubmit">
|
||||
<h2 class="form-title">疗休养满意度评价表</h2>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-label">疗休养服务单位:</div>
|
||||
<div class="form-text">{{formData.travelAgencyName}}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-label">疗休养地点:</div>
|
||||
<div class="form-text">{{formData.travelAgencyPlace}}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-label">教职工人数:</div>
|
||||
<div class="form-text">{{formData.teaNum}}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-label">疗休养时间:</div>
|
||||
<div class="form-text" v-if="formData.playStartTime && formData.playEndTime">
|
||||
{{moment(formData.playStartTime).format('YYYY年MM月DD日')}}
|
||||
至
|
||||
{{moment(formData.playEndTime).format('MM月DD日')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<div class="section-title">评分项目及分值(100分)</div>
|
||||
<div class="evaluation-desc">满意度评价(请您在认为的选项后空格内评分)</div>
|
||||
|
||||
<table class="score-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="item-column">评分项目</th>
|
||||
<th>好</th>
|
||||
<th>较好</th>
|
||||
<th>一般</th>
|
||||
<th>差</th>
|
||||
<th class="score-column">分数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in currentEvaluationItems" :key="index">
|
||||
<td class="item-name">{{item.title}}({{item.maxScore}}分)</td>
|
||||
<td
|
||||
v-for="(option, idx) in item.options"
|
||||
:key="idx"
|
||||
class="option-cell"
|
||||
:class="{'selected': getScoreLevel(formData[item.field], item) === idx}"
|
||||
@click="selectOption(index, idx)"
|
||||
>
|
||||
{{option.range}}
|
||||
</td>
|
||||
<td class="score-cell">
|
||||
<input
|
||||
type="number"
|
||||
v-model.number="formData[item.field]"
|
||||
:max="item.maxScore"
|
||||
min="0"
|
||||
required
|
||||
@input="validateScore($event, item)"
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="total-row">
|
||||
<td colspan="5" class="total-label">合计得分</td>
|
||||
<td class="total-value">{{totalScore}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<div class="section-title">对本次疗休养的整体评价及建议</div>
|
||||
<textarea
|
||||
v-model="formData.evaluateText"
|
||||
class="feedback-textarea"
|
||||
placeholder="请输入您的评价和建议"
|
||||
required
|
||||
rows="4"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<div class="form-row">
|
||||
<div class="form-label">本人姓名:</div>
|
||||
<div class="form-input">
|
||||
<input type="text" v-model="formData.userName" readonly required placeholder="请输入姓名">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-label">联系电话:</div>
|
||||
<div class="form-input">
|
||||
<input type="tel" v-model="formData.mobile" required placeholder="请输入电话">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row signature-row" v-if="show">
|
||||
<div class="form-label">签名:</div>
|
||||
<div class="form-input">
|
||||
<mobile-sign ref="signature" :is_value_base64="false" v-model="formData.signature"></mobile-sign>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="note-box">
|
||||
<div>注:</div>
|
||||
<div>1. 请在相应栏目中写上具体分数并合计得分。</div>
|
||||
<div>2. 得分90分(含)以上为满意,80分(含)-90分为合格,80分以下为不合格。</div>
|
||||
<div>3. 此表须由每团70%及以上的教职工(含领队)填写。</div>
|
||||
</div>
|
||||
|
||||
<div class="submit-box">
|
||||
<button type="submit" class="submit-btn">提交评价</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
enrollId: null,
|
||||
formData: {},
|
||||
evaluationItems: [
|
||||
{
|
||||
title: "住宿条件",
|
||||
maxScore: 20,
|
||||
field: "accommodationScore",
|
||||
options: [
|
||||
{ label: "好", range: "20-18" },
|
||||
{ label: "较好", range: "17-16" },
|
||||
{ label: "一般", range: "15-12" },
|
||||
{ label: "差", range: "<12" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "餐饮状况",
|
||||
maxScore: 20,
|
||||
field: "cateringScore",
|
||||
options: [
|
||||
{ label: "好", range: "20-18" },
|
||||
{ label: "较好", range: "17-16" },
|
||||
{ label: "一般", range: "15-12" },
|
||||
{ label: "差", range: "<12" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "行程景点安排",
|
||||
maxScore: 30,
|
||||
field: "travelScore",
|
||||
options: [
|
||||
{ label: "好", range: "30-25" },
|
||||
{ label: "较好", range: "24-20" },
|
||||
{ label: "一般", range: "19-15" },
|
||||
{ label: "差", range: "<15" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "车辆状况和司机服务",
|
||||
maxScore: 10,
|
||||
field: "guideScore",
|
||||
options: [
|
||||
{ label: "好", range: "10-9" },
|
||||
{ label: "较好", range: "8-7" },
|
||||
{ label: "一般", range: "6-5" },
|
||||
{ label: "差", range: "<5" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "导游服务",
|
||||
maxScore: 10,
|
||||
field: "guideScore",
|
||||
options: [
|
||||
{ label: "好", range: "10-9" },
|
||||
{ label: "较好", range: "8-7" },
|
||||
{ label: "一般", range: "6-5" },
|
||||
{ label: "差", range: "<5" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "安全措施",
|
||||
maxScore: 10,
|
||||
field: "safetyScore",
|
||||
options: [
|
||||
{ label: "好", range: "10-9" },
|
||||
{ label: "较好", range: "8-7" },
|
||||
{ label: "一般", range: "6-5" },
|
||||
{ label: "差", range: "<5" },
|
||||
],
|
||||
},
|
||||
],
|
||||
evaluationItemsType2: [
|
||||
{
|
||||
title: "住宿条件",
|
||||
maxScore: 30,
|
||||
field: "accommodationScore",
|
||||
options: [
|
||||
{ label: "好", range: "30-25" },
|
||||
{ label: "较好", range: "24-20" },
|
||||
{ label: "一般", range: "19-15" },
|
||||
{ label: "差", range: "<15" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "餐饮状况",
|
||||
maxScore: 30,
|
||||
field: "cateringScore",
|
||||
options: [
|
||||
{ label: "好", range: "30-25" },
|
||||
{ label: "较好", range: "24-20" },
|
||||
{ label: "一般", range: "19-15" },
|
||||
{ label: "差", range: "<15" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "行程景点安排",
|
||||
maxScore: 30,
|
||||
field: "travelScore",
|
||||
options: [
|
||||
{ label: "好", range: "30-25" },
|
||||
{ label: "较好", range: "24-20" },
|
||||
{ label: "一般", range: "19-15" },
|
||||
{ label: "差", range: "<15" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "安全措施",
|
||||
maxScore: 10,
|
||||
field: "safetyScore",
|
||||
options: [
|
||||
{ label: "好", range: "10-9" },
|
||||
{ label: "较好", range: "8-7" },
|
||||
{ label: "一般", range: "6-5" },
|
||||
{ label: "差", range: "<5" },
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
totalScore() {
|
||||
return this.currentEvaluationItems.reduce((sum, item) => {
|
||||
return sum + (Number(this.formData[item.field]) || 0);
|
||||
}, 0);
|
||||
},
|
||||
currentEvaluationItems() {
|
||||
return this.formData.type === 1
|
||||
? this.evaluationItems
|
||||
: this.evaluationItemsType2;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onOpen(id) {
|
||||
this.enrollId = id;
|
||||
this.getBasicInfo();
|
||||
this.show = true;
|
||||
},
|
||||
selectOption(itemIndex, optionIndex) {
|
||||
const item = this.currentEvaluationItems[itemIndex];
|
||||
const range = item.options[optionIndex].range;
|
||||
if (range.includes("-")) {
|
||||
const highScore = Number(range.split("-")[0]);
|
||||
this.formData[item.field] = highScore;
|
||||
} else if (range.includes("<")) {
|
||||
const threshold = Number(range.replace("<", ""));
|
||||
this.formData[item.field] = threshold - 1;
|
||||
}
|
||||
},
|
||||
onSubmit() {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
title: "提示",
|
||||
message: "您确定提交吗?",
|
||||
})
|
||||
.then(() => {
|
||||
$.post(
|
||||
"/platform/theRapyRecuperation/satisfactionEvaluate/submit",
|
||||
this.formData,
|
||||
).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$toast.success("提交成功");
|
||||
// this.show = false;
|
||||
this.$emit("refresh");
|
||||
} else {
|
||||
this.$toast(res.msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getScoreLevel(score, item) {
|
||||
if (!score && score !== 0) return -1;
|
||||
|
||||
const options = item.options;
|
||||
// 从最低分的选项开始判断
|
||||
for (let i = options.length - 1; i >= 0; i--) {
|
||||
const range = options[i].range;
|
||||
if (range.includes("<")) {
|
||||
const threshold = Number(range.replace("<", ""));
|
||||
if (score < threshold) {
|
||||
return i;
|
||||
}
|
||||
} else if (range.includes("-")) {
|
||||
const [max, min] = range.split("-").map(Number);
|
||||
if (score >= min && score <= max) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
validateScore(event, item) {
|
||||
const value = Number(event.target.value);
|
||||
if (isNaN(value)) {
|
||||
this.formData[item.field] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// 限制基本范围 0 到最大分值
|
||||
if (value > item.maxScore) {
|
||||
this.formData[item.field] = item.maxScore;
|
||||
return;
|
||||
} else if (value < 0) {
|
||||
this.formData[item.field] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据分值自动选中对应等级
|
||||
let selectedLevel = this.getScoreLevel(value, item);
|
||||
if (selectedLevel === -1) {
|
||||
// 如果没有找到对应等级,调整到最近的合法范围
|
||||
const options = item.options;
|
||||
for (let i = options.length - 1; i >= 0; i--) {
|
||||
const range = options[i].range;
|
||||
if (range.includes("<")) {
|
||||
const threshold = Number(range.replace("<", ""));
|
||||
if (value >= threshold) {
|
||||
this.formData[item.field] = threshold - 1;
|
||||
break;
|
||||
}
|
||||
} else if (range.includes("-")) {
|
||||
const [max, min] = range.split("-").map(Number);
|
||||
if (value > max) {
|
||||
this.formData[item.field] = max;
|
||||
break;
|
||||
} else if (value < min) {
|
||||
this.formData[item.field] = min;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
getBasicInfo() {
|
||||
$.post("/platform/theRapyRecuperation/satisfactionEvaluate/basicInfo", {
|
||||
enrollId: this.enrollId,
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = res.data;
|
||||
} else {
|
||||
this.$toast(res.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.satisfaction-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.satisfaction-header {
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
background-color: #1867b0;
|
||||
color: white;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 0;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.satisfaction-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0 12px 20px;
|
||||
}
|
||||
|
||||
.form-title {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
margin: 15px 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.form-row.signature-row {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.form-row.signature-row .form-label {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.form-row.signature-row .form-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
width: 130px;
|
||||
padding-right: 10px;
|
||||
line-height: 38px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.form-input input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin: 15px 0 5px 0;
|
||||
color: #333;
|
||||
border-left: 3px solid #1867b0;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.evaluation-desc {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.score-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.score-table th, .score-table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.score-table th {
|
||||
background-color: #f5f7fa;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.item-column {
|
||||
width: 30%;
|
||||
text-align: left;
|
||||
padding-left: 8px !important;
|
||||
}
|
||||
|
||||
.score-column {
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.item-name {
|
||||
text-align: left;
|
||||
padding-left: 8px !important;
|
||||
}
|
||||
|
||||
.option-cell {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.option-cell.selected {
|
||||
background-color: #edf4ff;
|
||||
color: #1867b0;
|
||||
}
|
||||
|
||||
.score-cell input {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
border: none;
|
||||
outline: none;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.total-row {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.total-label {
|
||||
text-align: right !important;
|
||||
padding-right: 8px !important;
|
||||
}
|
||||
|
||||
.total-value {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.feedback-textarea {
|
||||
width: 100%;
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
resize: vertical;
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.note-box {
|
||||
background-color: #f9f9f9;
|
||||
padding: 10px;
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.submit-box {
|
||||
margin: 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
background-color: #1867b0;
|
||||
color: white;
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 16px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form-text {
|
||||
flex: 1;
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
line-height: 38px;
|
||||
}
|
||||
`,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user