Skip to content

Commit

Permalink
新增: 留言功能
Browse files Browse the repository at this point in the history
  • Loading branch information
louise-bwsx committed Oct 17, 2024
1 parent 79f638c commit 0a2be61
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 15 deletions.
24 changes: 24 additions & 0 deletions src/api/routes/Question.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import express from "express";
import { transporter } from "../../config/email.js";

const router = express.Router();

router.post("/sendquestion", async (request, response, next) => {
//檢查是否重複註冊
const { name, email, question } = request.body;

try {
const mailOption = {
from: email,
to: "[email protected]",
subject: `${name} 問題`,
text: `我是${name} 問題: ${question}`,
};
await transporter.sendMail(mailOption);
} catch (error) {
console.error(`傳送搵替錯誤: ${error}`);
next(error);
}
});

export default router;
2 changes: 1 addition & 1 deletion src/components/CustomInputComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
required
spellcheck="false"
/>
<!-- 不知道怎麼用props動態調整 -->
<label>{{ placeholder }}</label>
</div>
</template>
Expand Down Expand Up @@ -41,6 +40,7 @@ export default {
<style scoped>
#cool_input {
position: relative;
width: 100%;
}
#cool_input input {
Expand Down
148 changes: 138 additions & 10 deletions src/components/portfolio/ContactMeComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,158 @@
<i class="fa-solid fa-phone mx-2"></i>
<div>0950074430</div>
</div>

<div class="d-flex mb-3">
<i class="fa-solid fa-envelope mx-2"></i>
<div>[email protected]</div>
</div>

<div class="d-flex mb-3">
<div class="col-lg-2 col-md-3 col-4">你的姓名:</div>
<input class="col" type=" text" />
<CustomInputComponent v-model="name" :placeholder="'你的姓名'" />
</div>

<div class="d-flex mb-3">
<div class="col-lg-2 col-md-3 col-4">你的電子郵件:</div>
<input class="col" type=" email" />
<CustomInputComponent v-model="email" :placeholder="'Email'" />
</div>
<div class="d-block mb-3">
<div>詢問內容:</div>
<textarea class="w-100" style="height: 250px">
這聯絡不到我不用送出</textarea
>

<!-- 沒辦法直接用CustomInput 沒辦法利用class修改到input 和 label -->
<div class="d-flex mb-3">
<div id="customTextArea">
<textarea
v-model="question"
type="text"
@input="onInput"
@blur="onBlur"
@keyup.enter="onEnter"
required
spellcheck="false"
/>
<label>詢問內容</label>
</div>
</div>

<button
@click="SendQuestion()"
:disabled="CantSendVerification()"
class="d-flex justify-content-center w-100 btn btn-outline-primary"
>
送出
送出 {{ GetDuration() }}
</button>
</div>
</div>
</template>

<script>
import CustomInputComponent from "../../components/CustomInputComponent.vue";
import { API_BASE_URL } from "../../config/api";
import axios from "axios";
export default {
components: { CustomInputComponent },
data() {
return {
name: "",
email: "",
question: "",
verified: false,
sendDuration: 0,
intervalID: "",
};
},
methods: {
async SendQuestion() {
try {
this.SetSendDuration();
const response = await axios.post(`${API_BASE_URL}/api/sendquestion`, {
name: this.name,
email: this.email,
question: this.question,
});
if (!response.data.success) {
alert(`${response.data.message}`);
return;
}
alert(`訊息已發送`);
} catch (error) {
alert(`發送訊息錯誤 ${error}`);
}
},
TimerCheck() {
this.sendDuration -= 1000;
if (this.sendDuration <= 0) {
this.ClearTimer();
}
},
ClearTimer() {
this.sendDuration = 0;
clearInterval(this.intervalID);
},
SetSendDuration() {
// 60000 毫秒等於 1 分鐘
this.ClearTimer();
this.sendDuration = 10000;
this.intervalID = setInterval(() => {
this.TimerCheck();
}, 1000);
},
CantSendVerification() {
return this.email == "" || this.sendDuration > 0;
},
GetDuration() {
if (this.sendDuration <= 0) {
return "";
}
const minutes = Math.floor(this.sendDuration / 60000); // 計算分鐘
const seconds = Math.floor((this.sendDuration % 60000) / 1000); // 計算秒數
// 確保秒數顯示兩位數,如 00:01
const formattedSeconds = seconds < 10 ? `0${seconds}` : seconds;
return `${minutes}:${formattedSeconds}`;
},
},
};
</script>

<style scoped>
#customTextArea {
position: relative;
width: 100%;
height: 100%;
}
#customTextArea textarea {
width: 100%;
height: 250px;
border-radius: 6px;
font-size: 18px;
padding: 10px 15px;
border: 2px #1cd679 solid;
background-color: white;
/* onClick的時候不會有預設藍色的outline */
outline: none;
color: black;
}
#customTextArea label {
position: absolute;
top: 10%;
left: 1.25%;
transform: translateY(-50%);
color: black;
font-size: 19px;
pointer-events: none;
transition: 0.3s;
}
#customTextArea textarea:focus ~ label,
#customTextArea textarea:valid ~ label {
top: 0px;
font-size: 16px;
padding: 0px 10px;
/* 這裡要用background一樣的顏色 不能用transparent 會蓋不住border */
background-color: white;
}
</style>
2 changes: 0 additions & 2 deletions src/pages/ForgotPassword.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<div class="mb-3 d-flex align-items-center">
<i class="fa-solid fa-envelope mx-2"></i>
<CustomInputComponent
class="w-100"
:placeholder="'Email'"
v-model="email"
aria-label="Email"
Expand All @@ -19,7 +18,6 @@
<div class="mb-3 d-flex align-items-center">
<i class="fa-solid fa-lock mx-2"></i>
<CustomInputComponent
class="w-100"
:placeholder="'驗證碼'"
v-model="verificationCode"
aria-label="VerificationCode"
Expand Down
2 changes: 0 additions & 2 deletions src/pages/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<div class="mb-3 d-flex align-items-center">
<i class="fa-solid fa-envelope mx-2"></i>
<CustomInputComponent
class="w-100"
:placeholder="'Email'"
v-model="email"
aria-label="Email"
Expand All @@ -19,7 +18,6 @@
<div class="mb-3 d-flex align-items-center position-relative">
<i class="fa-solid fa-lock mx-2"></i>
<CustomInputComponent
class="w-100"
:type="this.passwordVisibility ? 'text' : 'password'"
:placeholder="'密碼'"
v-model="password"
Expand Down
2 changes: 2 additions & 0 deletions src/pages/Portfolio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
class="w-100 h-100 object-fit-fill position-absolute start-0 z-n1"
src="/static/header.jpg"
/>

<!-- 漸層Mask -->
<div
class="position-absolute w-100 h-100 z-0"
Expand All @@ -14,6 +15,7 @@
mask-image: linear-gradient(to right, transparent, black 60%);
"
></div>

<!-- 作品集1 -->
<div class="row h-100">
<!-- 作品集1 左邊 -->
Expand Down
2 changes: 2 additions & 0 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import express from "express";
import cors from "cors";
import bodyParser from "body-parser";
import authRoutes from "./api/routes/Auth.js";
import questionRoutes from "./api/routes/Question.js";
import itemRoutes from "./api/routes/Items.js";
import cashierRoutes from "./api/routes/Cashier.js";
import b2cInvoiceRoutes from "./api/routes/B2CInvoice.js";
Expand Down Expand Up @@ -35,6 +36,7 @@ app.use(bodyParser.json());
// 提供靜態文件的路徑
app.use(express.static(path.join(__dirname, "public")));
app.use("/api", authRoutes);
app.use("/api", questionRoutes);
app.use("/api", itemRoutes);
app.use("/api", cashierRoutes);
app.use("/api", b2cInvoiceRoutes);
Expand Down

0 comments on commit 0a2be61

Please sign in to comment.