master
Lei OT 2 years ago
parent 97c2134455
commit 61e2568931

1
.gitignore vendored

@ -0,0 +1 @@
index-*.html

@ -1,6 +0,0 @@
# GHH-feedback
海外供应商反馈表
1. [供应商平台 反馈表录入地址](http://p.mycht.cn/php/gys.php/welcome/feedback_detail/256910/215427)
2. [海外反馈表案例-老版本](https://www.chinahighlights.com/customerservice/feedback/PostTourSurveyFormToWLGH.asp?LGC=1&COLI_SN=988185&MEI_SN=954295&Email=jennroth18@hotmail.com&ToC=0&ShowType=&page_class=4&dei_sn=28&country=30,490)
3. [海外反馈表录入地址](https://www.asiahighlights.com/customerfeedback/index.html?g=338947&v=30008)

@ -1,104 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Questionnaire</title>
<style>
body {
font-family: Arial, sans-serif;
}
.container {
max-width: 768px;
margin: 0 auto;
}
.question {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.radio-container {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 10px;
}
.radio-container input[type="radio"] {
display: none;
}
.radio-container label {
margin-left: 10px;
}
.radio-container input[type="radio"]:checked+.radio-label {
background-color: #d54e21;
color: white;
}
.radio-label {
display: inline-block;
padding: 10px 20px;
border: 1px solid #d54e21;
border-radius: 20px;
transition: all 0.3s ease;
}
@media (max-width: 768px) {
.container {
width: 100%;
padding: 0 15px;
}
.question label {
flex: 1 0 100%;
}
}
</style>
</head>
<body>
<div class="container">
<h1>Questionnaire</h1>
<form>
<h2>Question 1</h2>
<div class="question">
<div class="radio-container">
<input type="radio" id="excellent" name="question1">
<label for="excellent" class="radio-label">👍 Excellent</label>
</div>
<div class="radio-container">
<input type="radio" id="veryGood" name="question1">
<label for="veryGood" class="radio-label">🙂 Very Good</label>
</div>
<div class="radio-container">
<input type="radio" id="fair" name="question1">
<label for="fair" class="radio-label">😐 Fair</label>
</div>
<div class="radio-container">
<input type="radio" id="poor" name="question1">
<label for="poor" class="radio-label">🙁 Poor</label>
</div>
<div class="radio-container">
<input type="radio" id="unacceptable" name="question1">
<label for="unacceptable" class="radio-label">👎 Unacceptable</label>
</div>
</div>
<h2>Question 2</h2>
<div class="question">
<label><input type="radio" name="question2" value="option5"><span> 😃 Excellent</span></label>
<label><input type="radio" name="question2" value="option4"><span> 🙂 Very Good</span></label>
<label><input type="radio" name="question2" value="option3"><span> 😐 Fair</span></label>
<label><input type="radio" name="question2" value="option2"><span> ☹️ Poor</span></label>
<label><input type="radio" name="question2" value="option1"><span> 😠 Unacceptable</span></label>
</div>
<h2>Feedback</h2>
<textarea name="feedback" rows="4" cols="50" id="feedback"></textarea><br>
<input type="submit" value="Submit">
</form>
</div>
<script>
// var feedback = document.getElementById("feedback");
// feedback.onfocus = function() {
// alert("Please provide your valuable feedback!");
// }
</script>
</body>
</html>

@ -1,198 +0,0 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>test</title>
<link rel="stylesheet" href="./grid.css">
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon">
<!-- <script src="https://unpkg.com/unfetch/polyfill"></script> -->
<script src="./utils.js"></script>
<script src="./vue@2.js"></script>
</head>
<script>
</script>
<style>
/* @font-face {
font-family: 'DIN';
src: url('/dashboard/styles/DIN-BOLD-2.TTF');
font-style: normal;
font-weight: normal;
} */
body {
font-size: 12px;
font-family: DIN;
}
#main {
/* padding-right: 50px !important;
padding-left: 50px !important; */
margin-top: 12px;
margin-left: auto;
margin-right: auto;
}
.fz-22 {
font-size: 22px;
}
.z {
color: #E75A25;
}
.d {
color: #5EAD7D;
}
.info {
color: #343240;
}
/* loading */
#loading-mask {
width: 100vw;
height: 100vh;
background-color: #00000099;
position: fixed;
left: 0;
top: 0;
display: flex
}
.lds-facebook {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
margin: auto
}
.lds-facebook div {
display: inline-block;
position: absolute;
left: 8px;
width: 16px;
background: #fff;
animation: lds-facebook 1.2s cubic-bezier(0, .5, .5, 1) infinite
}
.lds-facebook div:nth-child(1) {
left: 8px;
animation-delay: -.24s
}
.lds-facebook div:nth-child(2) {
left: 32px;
animation-delay: -.12s
}
.lds-facebook div:nth-child(3) {
left: 56px;
animation-delay: 0
}
@keyframes lds-facebook {
0% {
top: 8px;
height: 64px
}
100%,
50% {
top: 24px;
height: 32px
}
}
/* end loading */
</style>
<body>
<input id="debug" type="checkbox" />
<label for="debug">Show grid lines</label>
<div class="content">
<div>Content</div>
<div class="popout">Popout</div>
<div class="feature">Feature</div>
<div class="full">Full</div>
</div>
<div class="content debug">
<div class="full"></div>
<div class="feature"></div>
<div class="popout"></div>
<div></div>
</div>
<div class="container-fluid" id="main">
<template>
<div v-for="(item, i) in feedbackItemList" :key="item.id">
<div>{{item.name}}</div>
</div>
</template>
<div id="loading-mask" v-if="loading">
<div class="lds-facebook">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<script defer>
// const HOST = `http://discovery.mycht.cn/api/index.php`;
const HOST = `http://localhost:3001/api/index.php`;
const defaultHeaders = { mode: 'no-cors', 'Sec-Fetch-Mode': 'no-cors' };
const rateList = [
{ name: 'Excellent', value: 5 },
{ name: 'Very Good', value: 4 },
{ name: 'Fair', value: 3 },
{ name: 'Poor', value: 2 },
{ name: 'Unacceptable', value: 1 }
];
const rateListMapped = rateList.reduce((r, v) => ({...r, [v.value + '']: v.name}), {});
console.log(rateListMapped);
/**
*
*/
const index = new Vue({
el: '#main',
data() {
return {
timer: null,
loading: false,
feedbackItemList: [],
};
},
created() {
console.log('invoke vue', typeof this);
this.initData();
},
methods: {
initData() {
this.loading = true;
this.getData();
},
getData() {
const that = this;
postForm(
`${HOST}/feedback/customer_feedback`,
// {group_id: 348323, tour_guide_id: 141},
{ group_id: 69291, tour_guide_id: 730 },
{ headers: { ...{} } }
).then((res) => {
that.loading = false;
that.feedbackItemList = res.feedbackItemList;
console.log(res)
});
},
},
});
</script>
</body>
</html>

@ -1,106 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: Arial, sans-serif;
}
.container {
max-width: 600px;
margin: 0 auto;
}
.question {
margin-bottom: 20px;
}
.feedback {
margin-top: 20px;
}
.star-rating {
direction: rtl;
display: inline-block;
}
.star-rating input[type=radio] {
display: none;
}
.star-rating label {
font-size: 30px;
color: lightgray;
cursor: pointer;
}
.star-rating input[type=radio]:checked ~ label,
.star-rating label:hover,
.star-rating label:hover ~ label {
color: #d54e21;
}
.rate-meaning {
display: inline-block;
margin-left: 15px;
vertical-align: middle;
color: #d54e21;
}
.rate-icon {
width: 20px;
height: 20px;
vertical-align: middle;
/* background: url('thumbsup.svg') no-repeat center; */
/* background-size: contain; */
filter: invert(27%) sepia(97%) saturate(7482%) hue-rotate(359deg) brightness(100%) contrast(107%);
}
.rate-icon path {
/* stroke: #d54e21; */
}
</style>
</head>
<body>
<div class="container">
<!-- <h1>Questionnaire</h1> -->
<form>
<div class="question">
<h4>Passion with Job</h4>
<div class="star-rating">
<input type="radio" id="q1-5" name="q1" value="5" checked>
<label for="q1-5"></label>
<input type="radio" id="q1-4" name="q1" value="4">
<label for="q1-4"></label>
<input type="radio" id="q1-3" name="q1" value="3">
<label for="q1-3"></label>
<input type="radio" id="q1-2" name="q1" value="2">
<label for="q1-2"></label>
<input type="radio" id="q1-1" name="q1" value="1">
<label for="q1-1"></label>
</div>
<span class="rate-meaning">
<span id="rate-text">Excellent</span>
</span>
</div>
<!-- <div class="feedback">
<h2>Any additional feedback?</h2>
<textarea id="feedback" name="feedback" rows="4" cols="50"></textarea>
</div>
<input type="submit" value="Submit"> -->
</form>
</div>
<script>
var ratings = {
"1": { text: "Unacceptable", icon: "./img/thumbsdown.svg" },
"2": { text: "Poor", icon: "./img/sadface.svg" },
"3": { text: "Fair", icon: "./img/neutralface.svg" },
"4": { text: "Very Good", icon: "./img/happyface.svg" },
"5": { text: "Excellent", icon: "./img/thumbsup.svg" }
};
var rateInputs = document.querySelectorAll('.star-rating input[type="radio"]');
var rateText = document.getElementById('rate-text');
var rateIcon = document.getElementById('rate-icon');
rateInputs.forEach(function(input) {
input.addEventListener('change', function() {
var rating = ratings[this.value];
rateText.textContent = rating.text;
// rateIcon.src = rating.icon;
});
});
</script>
</body>
</html>

@ -1,491 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body{font-family:Arial,sans-serif;color:#333}.text-primary{color:#b43c1a}h3,h5,p{margin:.5em 0}.header-m{background:#ad1818;color:#fff;padding:.5em}.header-pc{height:90px!important;display:flex;align-items:center;justify-content:flex-start;background:#ad1818;color:#fff;padding:0 20px}.header-pc img{position:absolute;top:0;margin-right:20px;height:104px;width:auto;border-radius:0 0 3px 3px;background-color:#fff;box-shadow:1px 1px 10px 1px rgba(77,77,77,.7);-webkit-box-shadow:1px 1px 10px 1px rgba(77,77,77,.7);-moz-box-shadow:1px 1px 10px 1px rgba(77,77,77,.7)}.header-pc h1{margin:0;margin-left:240px}.form-container{width:100%;max-width:768px;margin:0 auto;margin-top:1.5em}.question{display:flex;flex-direction:column;align-items:start;margin-bottom:10px}.question h4{position:sticky;top:0;background-color:#fff;margin-top:0;padding-top:1.33em}.question-items{display:flex;flex-direction:column;align-items:start}.options{display:flex;flex-direction:column;align-items:start;margin-bottom:10px}.options-row{flex-direction:row;justify-content:flex-end}.radio-container{display:flex;align-items:center;margin-bottom:10px}.radio-container input[type=radio]{display:none}.radio-container label{margin-left:8px}.radio-container input[type=radio]:checked+.radio-label{background-color:#d54e21;color:#fff}.radio-label{display:inline-block;padding:5px 10px;border:1px solid #d54e21;border-radius:20px;transition:all .3s ease;font-size:14px}label.radio-label svg{vertical-align:text-bottom}.feedback{margin-top:10px}.feedback textarea{width:90%;padding:10px;resize:vertical;border:1px solid #d54e21;border-radius:5px}.form-btn{display:block;width:100%;padding:10px;margin-top:20px;border:none;border-radius:20px;cursor:pointer;transition:all .3s ease;background:0 0;border:1px solid #d54e21;color:#d54e21}.submit-btn{background-color:#d54e21;color:#fff}.submit-btn:hover{background-color:#b43c1a}.cancel-btn:hover{background-color:#00000011}.info-container{display:flex;flex-direction:column;justify-content:space-between;margin-bottom:10px}.info-item{margin-bottom:10px}.info-item p{color:#b43c1a}.signature-pad{border:1px solid #d54e21;border-radius:5px;z-index:10}.signature-container{display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap}.button-container{margin-left:.5em;display:flex;flex-direction:column;justify-content:flex-start}.button{margin-top:1em;padding:10px;background-color:#d54e21;color:#fff;border:none;border-radius:5px;cursor:pointer}@media (min-width:768px){body{margin-left:0;margin-right:0;margin-top:0;padding-left:0;padding-right:0;padding-top:0}.question-items{width:100%;flex-direction:row;justify-content:space-between;align-items:baseline}.question-items .options{flex:1 1 auto}.options{flex-direction:row;justify-content:flex-end}.info-container{flex-direction:row}.info-item{flex:1;margin-right:10px;margin-bottom:0}.info-item:last-child{margin-right:0}.header-m{display:none}.signature-container{flex-direction:row}}@media (max-width:767px){.header-pc{display:none}}
</style>
<style>
#result{text-align:center;padding:20px}.bi-check-circle-fill,.bi-exclamation-circle-fill,.bi-x-circle-fill{fill:#d54e21}.bi-x-circle-fill{fill:#d54e21}
</style>
<style>
#loading-mask{width:100vw;height:100vh;background-color:#00000099;position:fixed;left:0;top:0;display:flex}.lds-facebook{display:inline-block;position:relative;width:80px;height:80px;margin:auto}.lds-facebook div{display:inline-block;position:absolute;left:8px;width:16px;background:#fff;animation:lds-facebook 1.2s cubic-bezier(0,.5,.5,1) infinite}.lds-facebook div:nth-child(1){left:8px;animation-delay:-.24s}.lds-facebook div:nth-child(2){left:32px;animation-delay:-.12s}.lds-facebook div:nth-child(3){left:56px;animation-delay:0}@keyframes lds-facebook{0%{top:8px;height:64px}100%,50%{top:24px;height:32px}}
</style>
<style>
.city-page{display:flex;flex-direction:column;align-items:center}.city-list{list-style-type:none;padding:0;width:200px;background-color:#fff;border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,.1)}.city-list li{padding:20px;border-top:1px solid #d54e21;border-bottom:1px solid #d54e21;transition:background-color .3s}.city-list li:hover{background-color:#d54e21;color:#fff}
</style>
<style>
.float-button{position:fixed;right:20px;bottom:120px;background-color:transparent;color:#d54e21;border:1px solid #d54e21;border-radius:50%;width:60px;height:60px;text-align:center;line-height:60px;font-size:24px;cursor:pointer;box-shadow:0 0 10px rgba(0,0,0,.1);z-index:1}.float-button:hover{background-color:#d54e21;color:#fff}.float-text{position:fixed;right:20px;bottom:190px;color:#d54e21;font-size:18px;text-align:right;z-index:-1}.expand-list{list-style-type:none;position:fixed;right:20px;bottom:190px;width:200px;background-color:#fff;border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,.1);padding:0;max-height:0;overflow:hidden;opacity:0;transition:max-height .5s ease,opacity .5s ease}.expand-list.open{max-height:500px;opacity:1}.expand-list li{padding:20px;border-bottom:1px solid #d54e21;transition:background-color .3s}.expand-list li:last-child{border-bottom:none}.expand-list li.active{color:#d54e21}.expand-list li:hover{background-color:#d54e21;color:#fff}
</style>
<script src="./utils.js"></script>
<script src="./vue@2.js"></script>
<script src="./signature_pad.umd.min.js"></script>
</head>
<body>
<!-- <div id="header">
<div id="mainnav" class="nav navbar navbar-inverse">
<div class="col-lg-3 col-sm-4 logobox"> <a href="//www.chinahighlights.com/"> <img src="https://www.chinahighlights.com/pic/logo/logo-132x104.png" alt="china highlights" class="img-responsive"> </a> </div>
<h1>Post Survey - Albee221228017</h1>
</div>
</div> -->
<!-- <img src="https://www.chinahighlights.com/pic/logo/logo-132x104.png" alt="Logo" class="logo"> -->
<div class="header-pc">
<a href="https://www.asiahighlights.com/">
<!-- <img src="https://www.chinahighlights.com/pic/logo/logo-132x104.png" alt="Logo"> -->
<img src="https://data.asiahighlights.com/pic/logo-ah.png" alt="Logo" width="130" height="104">
</a>
<h1>One Minute Feedback - Help Us Serve You Better</h1>
</div>
<div class="header-m">
<h1>One Minute Feedback - Help Us Serve You Better</h1>
</div>
<div class="form-container" id="main">
<div id="result" v-if="error">
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" fill="currentColor" class="bi bi-x-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.5-4.5a.5.5 0 0 0-.707 0L8 7.293 5.207 4.5a.5.5 0 0 0-.707.707L7.293 8l-2.793 2.793a.5.5 0 0 0 .707.707L8 8.707l2.793 2.793a.5.5 0 0 0 .707-.707L8.707 8l2.793-2.793a.5.5 0 0 0 0-.707z" />
</svg>
<h2>Error!</h2>
<p>The entered URL is wrong.</p>
</div>
<template v-else>
<div id="result" v-if="isFilled">
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" fill="currentColor" class="bi bi-check-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 10.417 5.384 8.323A.75.75 0 0 0 4.303 9.7l2.693 2.677a.75.75 0 0 0 1.086-.02l5.17-5.85a.75.75 0 0 0-.02-1.107z" />
</svg>
<h2>Thank you for your feedback!</h2>
<p>All actions are done.</p>
</div>
<template v-if="cityListPage">
<h4 v-if="!isFilled">Thank you for completing the Feedback Evaluation. Once submitted the tour guide would not be able to view your comments. </h4>
<div class="city-page">
<ul class="city-list" v-for="(city, index) in cityList" v-bind:key="city.cii_sn" v-on:click="selectCity(city)">
<li>{{city.cityName}}</li>
</ul>
</div>
</template>
<template v-if="!cityListPage">
<!-- <h1>One Minute Feedback - Help Us Serve You Better</h1> -->
<p>Did you enjoy your stay in the <span class="text-primary">{{group.cityName}}</span> area? Your honest feedback is appreciated to help us continually improve our service.</p>
<div class="info-container">
<div class="info-item">
<h3>Reference NO.:</h3>
<p id="referenceNo">{{group.groupNumber}}</p>
</div>
<div class="info-item">
<h3>Guide's Name:</h3>
<p id="guideName">{{group.tourGuideName}}</p>
</div>
<div class="info-item">
<h3>City:</h3>
<p id="city">{{group.cityName}}</p>
</div>
</div>
<hr>
<form class="form-container" id="myForm" action="/sub" method="post">
<div class="question">
<h4>1. How satisfied were you with your tour guide?</h4>
<div class="question-items" v-for="(q, qi) in feedbackItem.guide" v-bind:key="q.id">
<h5>{{q.Describe}}</h5>
<options-item question="guide" si="1" v-bind:qitem="q" v-bind:qi="qi" v-bind:key="q.id"></options-item>
</div>
</div>
<div class="question">
<h4>2. How about the Driver and Car/Van?</h4>
<div class="question-items" v-for="(q, qi) in feedbackItem.driver" v-bind:key="q.id">
<h5>{{q.Describe}}</h5>
<options-item question="Driver" v-bind:qitem="q" v-bind:si="2" v-bind:qi="qi" v-bind:key="q.id"></options-item>
</div>
</div>
<div class="question" v-if="feedbackItem.experience.length > 0">
<h4>3. General Experience with:</h4>
<div class="question-items" v-for="(q, qi) in feedbackItem.experience" v-bind:key="q.id">
<h5>{{q.Describe}}</h5>
<options-item question="Experience" v-bind:qitem="q" v-bind:si="3" v-bind:qi="qi" v-bind:key="q.id"></options-item>
</div>
</div>
<!-- debug: showPhotos -->
<div class="question " v-if="!showPhotos">
<h4>4. Would you give Asia Highlights permission to use photos taken by your tour guide(s) that contain your picture?</h2>
<div class="options options-row">
<div class="radio-container">
<input type="radio" id="photo-yes" name="photo_permission" value="1" v-bind:checked="feedbackEvaluation.usePhotos==1">
<label for="photo-yes" class="radio-label">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 1024 1024" fill="currentColor" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
<path d="M693.07 289.952v0.17l0.257-4.69-0.256 4.605z m309.823 164.932c-32.406-58.844-82.04-92.103-149.581-95.343-40.934-1.877-81.869-0.683-122.889-0.853l-5.543-0.17c0-0.939 0-1.45 0.17-1.962a778.607 778.607 0 0 0 11.855-88.35c2.302-28.143 3.837-56.37 4.35-84.598 0.425-24.39 2.728-48.866-0.854-73a121.95 121.95 0 0 0-69.247-96.281c-43.408-21.405-86.56-18.591-127.238 7.59-30.274 19.444-48.61 47.757-55.432 83.233-2.985 15.095-2.303 30.275-2.303 45.54 0.171 40.508-7.334 79.566-26.266 115.469-49.121 92.87-126.64 141.224-232.217 143.185-40.764 0.768-81.613 0.17-122.462 0.085-12.11 0-23.964 1.45-35.392 5.458C26.437 430.237 0 467.761 0 514.068v404.483c0 13.9 1.876 27.46 7.42 40.082 17.055 38.888 46.648 61.913 89.288 63.704 44.09 1.876 88.35 0.597 132.525 0.682 4.264 0 8.528-0.597 12.28-2.558 10.66-5.714 14.498-14.924 14.498-26.437-0.086-173.46 0-346.92 0-520.293 0-4.69-1.962-10.831 0.852-13.645 2.388-2.559 8.528-1.535 12.963-2.218a303.682 303.682 0 0 0 131.075-49.462 304.45 304.45 0 0 0 120.672-157.768c11.939-34.965 16.373-70.953 15.862-107.709-0.086-8.784-0.341-17.567 0.853-26.351a76.752 76.752 0 0 1 152.566 13.218c-0.086 45.71-1.28 91.335-5.288 136.875-3.155 36.67-6.822 73.34-18.761 108.561a25.072 25.072 0 0 0-0.939 13.56c2.815 13.048 12.793 20.637 27.29 20.723 49.377 0.17 98.584 0.511 147.876 0.597 16.885 0.085 33.43 1.705 49.292 7.93a128.346 128.346 0 0 1 76.41 156.575c-7.845 26.863-17.056 53.3-26.522 79.651-32.918 92.103-68.735 183.097-104.297 274.176a65.24 65.24 0 0 1-24.134 29.25c-15.692 11.258-33.686 14.157-52.448 14.157H388.536c-2.388 0-4.776 0-7.164 0.256a25.413 25.413 0 0 0-19.273 38.717c5.8 9.381 14.839 12.28 25.584 12.28 124.594-0.17 249.274-0.085 373.868-0.085 30.7 0 58.843-7.845 83.489-26.607 16.032-12.195 29.507-26.693 37.011-45.966 13.645-34.965 27.46-69.93 41.02-105.065a5069.898 5069.898 0 0 0 85.28-232.218c6.993-20.978 13.474-42.213 14.668-64.471a171.498 171.498 0 0 0-20.126-93.808zM199.214 972.022c-31.468-0.17-62.937 0-94.49-0.085-31.213 0-53.556-22.003-53.556-53.13v-405.08c0-30.616 22.002-52.874 52.703-53.044 32.15-0.256 64.301 0 96.452-0.17 4.434 0 4.35 1.96 4.35 5.116v250.723l0.084 250.297c0 4.605-1.194 5.373-5.543 5.373z"></path>
</svg> Yes</label>
</div>
<div class="radio-container">
<input type="radio" id="photo-no" name="photo_permission" value="0" v-bind:checked="feedbackEvaluation.usePhotos==0">
<label for="photo-no" class="radio-label">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 1024 1024" fill="currentColor" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
<path d="M48.464 631.08700001c48.699 62.928 143.57 58.704 250.284 56.35599999-2.209 25.413-4.421 50.832-6.63 76.246-19.954 124.422 6.40100001 225.148 107.739 243.653 25.172 4.597 57.261 1.206 76.246-6.63 50.216-20.73 66.13900001-69.316 76.244-130.943 6.03-36.774-4.886-78.582 3.314-111.053 10.411-41.21899999 42.025-71.825 74.588-91.163 39.233-23.301 89.891-37.523 142.546-46.411 84.102-14.197 199.811 28.752 228.737-39.78 12.732-30.167 4.972-88.664 4.97199999-127.629 0-98.887 0-197.80700001 1e-8-296.694 0.005-56.361 3.995-104-28.178-127.629-32.115-23.589-175.184-12.1-232.052-11.602 0 183.962 0 367.98499999 0 551.951-108.558 5.808-220.308 82.921-245.311 174.039-18.901 68.882 15.14099999 176.963-44.751 203.87300001-126.281 56.74-118.138-130.886-104.42199999-217.13100001 3.316-33.147 6.63-66.303 9.94499999-99.451 0-1.65700001 0-3.314 0-4.97200001-88.64 3.39599999-225.769 27.517-270.174-31.49199999-24.46-32.502-25.201-96.493-11.603-142.546 25.901-87.719 115.413-308.391 174.039-354.708 35.045-27.688 60.869-9.38899999 114.369-18.232 97.231-1.658 194.49-3.314 291.721-4.972 0-18.784 0-37.573 0-56.354-131.482 1.657-263.004 3.314-394.486 4.971-26.544 7.717-60.47599999 39.373-76.246 59.671-25.17 32.401-38.386 72.814-59.67100001 109.396-42.378 72.842-80.09 159.218-104.42299999 246.97-18.87300001 68.061-11.397 147.559 23.206 192.269zM802.631 74.165c46.958 0 93.93099999 0 140.89-1e-8 15.929 26.039 6.63 94.318 6.62999999 132.60100001-0.553 117.671-1.106 235.37700001-1.65699999 353.05-22.059 12.835-111.344 5.428-145.861 4.972 0-163.524 0-327.101 0-490.623z"></path>
</svg> No</label>
</div>
</div>
</div>
<div class="feedback question">
<h4>Any other comments that you would like to share with us?</h4>
<textarea name="comments" rows="4" v-bind:value="feedbackEvaluation.otherComments"></textarea>
</div>
<div class="signature">
<h4>Signature:</h4>
<div class="signature-container">
<canvas id="signature-pad" class="signature-pad" width='auto' height=200></canvas>
<div class="button-container">
<button type="button" id="clear" class="button" v-on:click="clearSignature()">Clear</button>
<!-- <button type="button" id="save" class="button">Save</button> -->
</div>
</div>
</div>
<!-- <input type="submit" value="Submit"> -->
<!-- <button type="submit" id="submit" class="submit-btn">Finish & Submit</button> -->
<button type="button" id="submit_a" class="form-btn submit-btn" v-on:click="submitForm">Finish & Submit</button>
<button type="button" id="back" class="form-btn cancel-btn" v-on:click="cancel">Cancel</button>
</form>
<span id="currentCity" class="float-text" v-show="!cityListOpen">{{group.cityName}}</span>
<button class="float-button" v-on:click="toggleCityList"></button>
<!-- onclick="toggleCityList()" -->
<ul v-bind:class="['expand-list', cityListOpen ? 'open' : '']">
<li v-for="city in cityList" v-bind:key="city.cii_sn" v-on:click="selectCity(city)" v-bind:class="{'active': city.cii_sn === currentCity.cii_sn}">{{city.cityName}}</li>
</ul>
</template>
</template>
<div id="loading-mask" v-if="loading">
<div class="lds-facebook">
<div></div>
<div></div>
<div></div>
</div>
</div>
</div>
<script defer>
/**
*
*/
const thumbsUp = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 1024 1024" fill="currentColor" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><path d="M693.07 289.952v0.17l0.257-4.69-0.256 4.605z m309.823 164.932c-32.406-58.844-82.04-92.103-149.581-95.343-40.934-1.877-81.869-0.683-122.889-0.853l-5.543-0.17c0-0.939 0-1.45 0.17-1.962a778.607 778.607 0 0 0 11.855-88.35c2.302-28.143 3.837-56.37 4.35-84.598 0.425-24.39 2.728-48.866-0.854-73a121.95 121.95 0 0 0-69.247-96.281c-43.408-21.405-86.56-18.591-127.238 7.59-30.274 19.444-48.61 47.757-55.432 83.233-2.985 15.095-2.303 30.275-2.303 45.54 0.171 40.508-7.334 79.566-26.266 115.469-49.121 92.87-126.64 141.224-232.217 143.185-40.764 0.768-81.613 0.17-122.462 0.085-12.11 0-23.964 1.45-35.392 5.458C26.437 430.237 0 467.761 0 514.068v404.483c0 13.9 1.876 27.46 7.42 40.082 17.055 38.888 46.648 61.913 89.288 63.704 44.09 1.876 88.35 0.597 132.525 0.682 4.264 0 8.528-0.597 12.28-2.558 10.66-5.714 14.498-14.924 14.498-26.437-0.086-173.46 0-346.92 0-520.293 0-4.69-1.962-10.831 0.852-13.645 2.388-2.559 8.528-1.535 12.963-2.218a303.682 303.682 0 0 0 131.075-49.462 304.45 304.45 0 0 0 120.672-157.768c11.939-34.965 16.373-70.953 15.862-107.709-0.086-8.784-0.341-17.567 0.853-26.351a76.752 76.752 0 0 1 152.566 13.218c-0.086 45.71-1.28 91.335-5.288 136.875-3.155 36.67-6.822 73.34-18.761 108.561a25.072 25.072 0 0 0-0.939 13.56c2.815 13.048 12.793 20.637 27.29 20.723 49.377 0.17 98.584 0.511 147.876 0.597 16.885 0.085 33.43 1.705 49.292 7.93a128.346 128.346 0 0 1 76.41 156.575c-7.845 26.863-17.056 53.3-26.522 79.651-32.918 92.103-68.735 183.097-104.297 274.176a65.24 65.24 0 0 1-24.134 29.25c-15.692 11.258-33.686 14.157-52.448 14.157H388.536c-2.388 0-4.776 0-7.164 0.256a25.413 25.413 0 0 0-19.273 38.717c5.8 9.381 14.839 12.28 25.584 12.28 124.594-0.17 249.274-0.085 373.868-0.085 30.7 0 58.843-7.845 83.489-26.607 16.032-12.195 29.507-26.693 37.011-45.966 13.645-34.965 27.46-69.93 41.02-105.065a5069.898 5069.898 0 0 0 85.28-232.218c6.993-20.978 13.474-42.213 14.668-64.471a171.498 171.498 0 0 0-20.126-93.808zM199.214 972.022c-31.468-0.17-62.937 0-94.49-0.085-31.213 0-53.556-22.003-53.556-53.13v-405.08c0-30.616 22.002-52.874 52.703-53.044 32.15-0.256 64.301 0 96.452-0.17 4.434 0 4.35 1.96 4.35 5.116v250.723l0.084 250.297c0 4.605-1.194 5.373-5.543 5.373z"></path></svg>';
const thumbsDown = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 1024 1024" fill="currentColor" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><path d="M48.464 631.08700001c48.699 62.928 143.57 58.704 250.284 56.35599999-2.209 25.413-4.421 50.832-6.63 76.246-19.954 124.422 6.40100001 225.148 107.739 243.653 25.172 4.597 57.261 1.206 76.246-6.63 50.216-20.73 66.13900001-69.316 76.244-130.943 6.03-36.774-4.886-78.582 3.314-111.053 10.411-41.21899999 42.025-71.825 74.588-91.163 39.233-23.301 89.891-37.523 142.546-46.411 84.102-14.197 199.811 28.752 228.737-39.78 12.732-30.167 4.972-88.664 4.97199999-127.629 0-98.887 0-197.80700001 1e-8-296.694 0.005-56.361 3.995-104-28.178-127.629-32.115-23.589-175.184-12.1-232.052-11.602 0 183.962 0 367.98499999 0 551.951-108.558 5.808-220.308 82.921-245.311 174.039-18.901 68.882 15.14099999 176.963-44.751 203.87300001-126.281 56.74-118.138-130.886-104.42199999-217.13100001 3.316-33.147 6.63-66.303 9.94499999-99.451 0-1.65700001 0-3.314 0-4.97200001-88.64 3.39599999-225.769 27.517-270.174-31.49199999-24.46-32.502-25.201-96.493-11.603-142.546 25.901-87.719 115.413-308.391 174.039-354.708 35.045-27.688 60.869-9.38899999 114.369-18.232 97.231-1.658 194.49-3.314 291.721-4.972 0-18.784 0-37.573 0-56.354-131.482 1.657-263.004 3.314-394.486 4.971-26.544 7.717-60.47599999 39.373-76.246 59.671-25.17 32.401-38.386 72.814-59.67100001 109.396-42.378 72.842-80.09 159.218-104.42299999 246.97-18.87300001 68.061-11.397 147.559 23.206 192.269zM802.631 74.165c46.958 0 93.93099999 0 140.89-1e-8 15.929 26.039 6.63 94.318 6.62999999 132.60100001-0.553 117.671-1.106 235.37700001-1.65699999 353.05-22.059 12.835-111.344 5.428-145.861 4.972 0-163.524 0-327.101 0-490.623z"></path></svg>';
const happyFace = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M8 14s1.5 2 4 2 4-2 4-2"></path><line x1="9" y1="9" x2="9.01" y2="9"></line><line x1="15" y1="9" x2="15.01" y2="9"></line></svg>';
const NeutralFace = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="9" y1="9" x2="9.01" y2="9"></line><line x1="15" y1="9" x2="15.01" y2="9"></line><line x1="9" y1="15" x2="15" y2="15"></line></svg>';
const sadFace = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M16 16s-1.5-2-4-2-4 2-4 2"></path><line x1="9" y1="9" x2="9.01" y2="9"></line><line x1="15" y1="9" x2="15.01" y2="9"></line></svg>';
const rateList = [
{ name: 'Excellent', value: 5, url: './img/thumbsup.svg', svg: thumbsUp },
{ name: 'Very Good', value: 4, url: './img/happyface.svg', svg: happyFace },
{ name: 'Fair', value: 3, url: './img/neutralface.svg', svg: NeutralFace },
{ name: 'Poor', value: 2, url: './img/sadface.svg', svg: sadFace },
{ name: 'Unacceptable', value: 1, url: './img/thumbsdown.svg', svg: thumbsDown }
];
const rateListMapped = rateList.reduce((r, v) => ({ ...r, [v.value + '']: v }), {});
// console.log(rateListMapped);
// 定义名为 options-item 的新组件
Vue.component('options-item', {
props: ['question', 'si', 'qi', 'qitem'],
template: '<div class="options">' +
'<div class="radio-container" v-for="item in rateList">' +
'<input type="radio" v-bind:id="item.value + \'-\' + si + \'-\' + qi" v-bind:name="\'rate-\'+qitem.id" v-bind:value="item.value" v-bind:checked="qitem.rate===item.value">' +
'<label v-bind:for="item.value+\'-\' + si + \'-\' + qi" class="radio-label"><span v-html="item.svg"></span> {{item.name}}</label>' +
'</div>' +
'</div>',
data() {
return {
rateList: rateList
}
},
});
</script>
<script defer>
const defaultHeaders = { mode: 'no-cors', 'Sec-Fetch-Mode': 'no-cors' };
const HOST = `http://discovery.mycht.cn/api/index.php`;
// const HOST = `http://localhost:3001/api/index.php`;
const HOST100 = `http://202.103.68.144:890/service-CooperateSOA`;
const index = new Vue({
el: '#main',
data() {
return {
timer: null,
error: false,
param: {},
loading: false,
cityListPage: true,
cityList: [],
currentCity: {},
cityListOpen: false,
isFilled: false,
feedbackItemList: [],
feedbackItem: { guide: [], driver: [], experience: [] },
tourGuideList: [],
feedbackEvaluation: {},
group: {},
showPhotos: false,
signaturePad: null,
};
},
created() {
console.log('invoke vue', typeof this);
this.initData();
},
methods: {
initData() {
var urlParams = new URLSearchParams(window.location.search);
for (const param of urlParams) {
this.param[param[0]] = param[1];
}
if (!(this.param.v && this.param.g)) {
this.error = true;
return false;
}
this.loading = true;
this.getCityList();
},
getCityList() {
if (!(this.param.v && this.param.g)) {
return false;
}
const that = this;
get(
`${HOST100}/get_feedback_city`,
// g=338947&v=30008&e=245176&c=1186
{ GRI_SN: that.param.g, VEI_SN: that.param.v, lgc: 1 },
{ headers: { ...{} } }
).then((res) => {
that.loading = false;
that.cityList = res.cityList;
// that.selectCity(res.cityList[0]);
});
},
selectCity(city) {
this.cityListPage = false;
this.loading = true;
const _param = {
GRI_SN: this.param.g,
VEI_SN: this.param.v,
// EOI_SN: this.param.e,
EOI_SN: city.cii_sn === 1186 ? 245176 : 245988, // debug: 接口未返回
CITY_SN: city.cii_sn,
lgc: 1
};
this.currentCity = { ...city, ..._param };
this.getData(_param);
window.scrollTo({ top: 100, behavior: 'smooth' });
this.cityListOpen = false;
},
initSignature() {
var canvas = document.getElementById('signature-pad');
this.signaturePad = new SignaturePad(canvas, {
penColor: "rgb(50, 50, 50)",
});
},
clearSignature() {
this.signaturePad.clear();
},
getData(param) {
const that = this;
get(
// `${HOST}/feedback/customer_feedback`,
`${HOST100}/get_feedback_service_item`,
// {group_id: 69291, tour_guide_id: 730},
// { group_id: that.param.g, tour_guide_id: that.param.tg },
// g=338947&v=30008&e=245176&c=1186
param,
// { GRI_SN: that.param.g, VEI_SN: that.param.v, EOI_SN: that.param.e, CITY_SN: that.param.c, lgc: 1 },
{ headers: { ...{} } }
).then((res) => {
that.loading = false;
const itemGroup = groupBy(res.feedbackItemList, ele => ele.type);
that.feedbackItem.guide = itemGroup.W ? itemGroup.W : [];
that.feedbackItem.driver = itemGroup.Y ? itemGroup.Y : [];
// that.feedbackItem.experience = [
// ...(itemGroup['7'] || []),
// ...(itemGroup.C || []),
// ...(itemGroup.A || []).map(ele => ({ ...ele, Describe: 'Hotel\n' + ele.name })),];
let experience = [];
if (itemGroup['7']) {
experience = experience.concat(itemGroup['7']);
}
if (itemGroup.C) {
experience = experience.concat(itemGroup.C);
}
if (itemGroup.A) {
experience = experience.concat(itemGroup.A.map(function (ele) {
var newEle = Object.assign({}, ele);
newEle.Describe = 'Hotel\n' + ele.name;
return newEle;
}));
}
that.feedbackItem.experience = experience;
that.feedbackItemList = res.feedbackItemList;
that.tourGuideList = res.tourGuideList;
that.feedbackEvaluation = res.feedbackEvaluation[0];
that.group = res.group[0];
that.isFilled = isEmpty(res.feedbackEvaluation[0].feedbackId); // debug: !isEmpty
that.showPhotos = res.group[0].inTheEnd;
// alert("Thank you for completing the Feedback Evaluation. Once submitted the tour guide would not be able to view your comments. "); // debug: 1
that.initSignature();
});
},
submitForm() {
const that = this;
if (that.signaturePad.isEmpty()) {
alert("Please provide a signature first.");
event.preventDefault();
} else {
that.loading = true;
// var data = that.signaturePad.toDataURL(); // default: image/png
var data = that.signaturePad.toDataURL("image/svg+xml");
var form = document.getElementById('myForm');
// Create a FormData instance
var formData = new FormData(form);
formData.append('signature', data);
// Convert the FormData to a plain object
var formValues = Array.from(formData.entries()).reduce((obj, [key, value]) => {
obj[key] = value;
return obj;
}, {});
// Print the form values to the console
var rateArr = that.feedbackItemList.map(ele => {
return { id: ele.id, sn: ele.sn, rate: formValues[`rate-${ele.id}`] || 0, };
});
// Send data to server along with the form data...
// Submit the form manually
// form.submit();
postForm(
`${HOST100}/save_feedback`,
{
EOI_SN: that.currentCity.EOI_SN,
GRI_SN: that.currentCity.GRI_SN,
VEI_SN: that.currentCity.VEI_SN,
// country_id:,
city_id: that.currentCity.cii_sn,
tour_guide_id: that.currentCity.tourGuideId,
use_the_photos: formValues.photo_permission || -1, // todo: 没有更新成功
other_comments: formValues.comments,
service_item_answer: JSON.stringify(rateArr),
signature_data_url: formValues.signature, // todo: 没有更新成功
},
{ headers: { ...{} } }
).then(res => {
that.loading = false;
if (res.errcode == 0) {
that.isFilled = true;
that.cityListPage = true;
that.currentCity = {};
} else { }
});
// window.location.href = "http://example.com/thankyou";
}
},
cancel() {
this.cityListPage = true;
this.currentCity = {};
},
toggleCityList() {
this.cityListOpen = !this.cityListOpen;
},
},
});
</script>
<script>
// debugger
// var canvas = document.getElementById('signature-pad');
// var signaturePad = new SignaturePad(canvas);
// // Clear button
// var clearButton = document.getElementById('clear');
// clearButton.addEventListener('click', function () {
// signaturePad.clear();
// });
// Save button
// var saveButton = document.getElementById('save');
// saveButton.addEventListener('click', function () {
// if (signaturePad.isEmpty()) {
// alert("Please provide a signature first.");
// } else {
// var data = signaturePad.toDataURL('image/png');
// console.log(data);
// // Send data to server instead...
// }
// });
// Submit button
// var submitButton = document.getElementById('submit');
// submitButton.addEventListener('click', function () {
// event.preventDefault(); // debug: 0
// if (signaturePad.isEmpty()) {
// alert("Please provide a signature first.");
// event.preventDefault();
// } else {
// var data = signaturePad.toDataURL('image/png');
// console.log(data);
// var form = document.getElementById('myForm');
// // Create a FormData instance
// var formData = new FormData(form);
// formData.append('signature', data);
// // Convert the FormData to a plain object
// var formValues = Array.from(formData.entries()).reduce((obj, [key, value]) => {
// obj[key] = value;
// return obj;
// }, {});
// // Print the form values to the console
// console.log(formValues);
// alert("Thank you for your feedback!");
// // Send data to server along with the form data...
// // Submit the form manually
// form.submit();
// // window.location.href = "http://example.com/thankyou";
// }
// });
// document.getElementById("myForm").addEventListener("submit", function (event) {
// var name = document.getElementById('name').value;
// var email = document.getElementById('email').value;
// if (name == "" || email == "") {
// alert("Both fields must be filled out");
// event.preventDefault();
// }
// if (signaturePad.isEmpty()) {
// alert("Please provide a signature first.");
// event.preventDefault();
// } else {
// var data = signaturePad.toDataURL('image/png');
// console.log(data);
// // Send data to server along with the form data...
// }
// event.preventDefault();
// });
</script>
</body>
</html>

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save