From 8a04c4e72eb92ecb92d2813310485a845177c4fe Mon Sep 17 00:00:00 2001 From: brianling Date: Mon, 10 Jun 2024 23:57:29 +0800 Subject: [PATCH] feat(.): Achieve the sms code send --- components/Default/Header.vue | 56 ++++---- nuxt.config.ts | 13 +- package.json | 1 + pages/admin/index.vue | 78 +++++++++++ pages/apply/index.vue | 175 +++++++++++++++--------- pages/login/index.vue | 72 ++++++++-- pages/register/index.vue | 243 +++++++++++++++++++++++++++++----- pages/user/index.vue | 6 + prisma/schema.prisma | 11 ++ server/api/test/code.ts | 27 ++++ server/api/test/index.ts | 43 +++++- server/api/test/reg.ts | 19 +++ server/api/test/sms.ts | 93 +++++++++++++ yarn.lock | 5 + 14 files changed, 690 insertions(+), 152 deletions(-) create mode 100644 pages/admin/index.vue create mode 100644 pages/user/index.vue create mode 100644 server/api/test/code.ts create mode 100644 server/api/test/reg.ts create mode 100644 server/api/test/sms.ts diff --git a/components/Default/Header.vue b/components/Default/Header.vue index df479dd..d38dc4f 100644 --- a/components/Default/Header.vue +++ b/components/Default/Header.vue @@ -1,24 +1,20 @@ \ No newline at end of file + diff --git a/nuxt.config.ts b/nuxt.config.ts index 64fda6e..c73c6f5 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -1,8 +1,11 @@ // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ devtools: { enabled: true }, - modules: [ - "@element-plus/nuxt", - '@vueform/nuxt' - ], -}) \ No newline at end of file + runtimeConfig: { + apiSecret: "", + apiOpenid: "", + apiApikey: "", + apiSmsId: 0, + }, + modules: ["@element-plus/nuxt", "@vueform/nuxt"], +}); diff --git a/package.json b/package.json index 4b117ba..931bd05 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "element-plus": "^2.7.4", "nuxt": "^3.11.2", "prisma": "^5.15.0", + "quanmsms": "^1.0.2", "typescript": "^5.4.5", "vue": "^3.4.27", "vue-router": "^4.3.2" diff --git a/pages/admin/index.vue b/pages/admin/index.vue new file mode 100644 index 0000000..9ad99b2 --- /dev/null +++ b/pages/admin/index.vue @@ -0,0 +1,78 @@ + + diff --git a/pages/apply/index.vue b/pages/apply/index.vue index e2e0d4e..09b517c 100644 --- a/pages/apply/index.vue +++ b/pages/apply/index.vue @@ -1,76 +1,123 @@ \ No newline at end of file +import PhoneElemen from "@vueform/vueform"; +const form = ref(); + diff --git a/pages/login/index.vue b/pages/login/index.vue index c042fc0..e7016ce 100644 --- a/pages/login/index.vue +++ b/pages/login/index.vue @@ -1,15 +1,63 @@ \ No newline at end of file +import PhoneElemen from "@vueform/vueform"; +const form = ref(); + diff --git a/pages/register/index.vue b/pages/register/index.vue index 5c19d07..612bb1c 100644 --- a/pages/register/index.vue +++ b/pages/register/index.vue @@ -1,34 +1,211 @@ - \ No newline at end of file + + + 注册页面 + + +
+ + + + + + + + + + + 已阅读并同意《用户协议》 + + 希望获取最新资讯 + + + +
+ + diff --git a/pages/user/index.vue b/pages/user/index.vue new file mode 100644 index 0000000..cbdbab7 --- /dev/null +++ b/pages/user/index.vue @@ -0,0 +1,6 @@ + diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3770668..bc89aee 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -18,6 +18,11 @@ model User { applications Application[] } +model Adminer { + id Int @id @default(autoincrement()) + adminId Int +} + model Application { id Int @id @default(autoincrement()) name String @@ -30,3 +35,9 @@ model Application { applicant User @relation(fields: [applicantId], references: [id]) applicantId Int } +model Register { + id Int @id @default(autoincrement()) + phone String + deadline DateTime + code String +} \ No newline at end of file diff --git a/server/api/test/code.ts b/server/api/test/code.ts new file mode 100644 index 0000000..2d0f25e --- /dev/null +++ b/server/api/test/code.ts @@ -0,0 +1,27 @@ +import { PrismaClient } from "@prisma/client"; +const db = new PrismaClient(); +export default defineEventHandler(async (event) => { + const body = await readBody(event); + const register = (await db.register.findFirst({ + where: { + phone: body.phone, + }, + orderBy: { + deadline: "desc", // 'asc' 表示升序,'desc' 表示降序 + }, + })) || { + deadline: new Date(), + }; + const deadlineDate = new Date(register.deadline); + const now = new Date(); + if (now > deadlineDate) { + return { code: 2, msg: "验证码超时了,请重新发送" }; + } else if (register.code != body.code) { + console.log(body.code + " phone " + register.phone + " " + register.code); + return { code: 0, msg: "验证码错误" }; + } else if (register.code == body.code) { + return { code: 1, msg: "验证码正确" }; + } else { + return { code: -1, msg: "未知错误" }; + } +}); diff --git a/server/api/test/index.ts b/server/api/test/index.ts index 638aad6..9473bdf 100644 --- a/server/api/test/index.ts +++ b/server/api/test/index.ts @@ -1,9 +1,38 @@ -import { PrismaClient } from "@prisma/client" +import { PrismaClient } from "@prisma/client"; -const db = new PrismaClient() +const db = new PrismaClient(); -export default defineEventHandler(async(event) => { - const body = await readBody(event) - console.info(body) - return body -}) \ No newline at end of file +export default defineEventHandler(async (event) => { + const body = await readBody(event); + console.info(body); + let isSend = + (await db.register.findFirst({ + where: { + phone: body.phone, + }, + })) != null; + if (isSend) { + const register = (await db.register.findFirst({ + where: { + phone: body.phone, + }, + orderBy: { + deadline: "desc", // 'asc' 表示升序,'desc' 表示降序 + }, + })) || { + deadline: new Date(), + }; + const deadlineDate = new Date(register.deadline); + const now = new Date(); + if (now <= deadlineDate) { + return { code: 2, msg: "三分钟内请勿重发送" }; + } else { + return { + code: -1, + msg: + "发送成功" + now + "<=" + deadlineDate + ":" + (now <= deadlineDate), + }; + } + } + return isSend; +}); diff --git a/server/api/test/reg.ts b/server/api/test/reg.ts new file mode 100644 index 0000000..18b157c --- /dev/null +++ b/server/api/test/reg.ts @@ -0,0 +1,19 @@ +import { PrismaClient } from "@prisma/client"; +const db = new PrismaClient(); +export default defineEventHandler(async (event) => { + const body = await readBody(event); + return { + username: + (await db.user.findFirst({ + where: { + username: body.username, + }, + })) == null, + phone: + (await db.user.findFirst({ + where: { + phone: body.phone, + }, + })) == null, + }; +}); diff --git a/server/api/test/sms.ts b/server/api/test/sms.ts new file mode 100644 index 0000000..1d9c158 --- /dev/null +++ b/server/api/test/sms.ts @@ -0,0 +1,93 @@ +import { PrismaClient } from "@prisma/client"; +import qmAPI from "quanmsms"; + +const config = useRuntimeConfig(); +const smsApi = new qmAPI(config.apiOpenid.toString(), { + sms: { + apiKey: config.apiApikey, + }, +}); +const db = new PrismaClient(); +function generateRandomCode(length: number) { + let code = ""; + //const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';复杂验证码 + const possible = "0123456789"; + for (let i = 0; i < length; i++) { + code += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return code; +} +function generateDeadline() { + const now = new Date(); // 获取当前时间 + const threeMinutesLater = new Date(now.getTime() + 3.5 * 60 * 1000); // 加上3分钟 + return threeMinutesLater.toISOString(); // 转换为ISO格式字符串 +} + +function send(telstr: string) { + let tel = parseInt(telstr); + const code = generateRandomCode(6); + let param = { + tel: tel, + model_id: config.apiSmsId.toString(), + model_args: { + //模板id对应的变量key值,object格式,内部自动处理成平台要求的str + code: code, + // 如果你的模板没变量,该值可为空 + }, + }; + return smsApi + .sendSMS(param) + .then((response: { code: number; state: number }) => { + if (response.state == 200) { + db.register + .create({ + data: { + phone: telstr, + deadline: generateDeadline(), + code: code, + }, + }) + .then((reg) => { + if (reg.phone == telstr) { + console.info(telstr + "发送成功"); + } + }); + return { code: 1, msg: "发送成功" }; + } else { + console.info(tel); + return { code: 0, msg: "发送失败", error: response }; + } + // 你的业务代码 + }); +} + +export default defineEventHandler(async (event) => { + const body = await readBody(event); + let isSend = + (await db.register.findFirst({ + where: { + phone: body.phone, + }, + })) != null; + if (isSend) { + const register = (await db.register.findFirst({ + where: { + phone: body.phone, + }, + orderBy: { + deadline: "desc", // 'asc' 表示升序,'desc' 表示降序 + }, + })) || { + deadline: new Date(), + }; + const deadlineDate = new Date(register.deadline); + const now = new Date(); + if (now <= deadlineDate) { + return { code: 2, msg: "三分钟内请勿重发送" }; + } else { + return send(body.phone); + } + } else { + return send(body.phone); + } +}); diff --git a/yarn.lock b/yarn.lock index eae6704..60795ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4858,6 +4858,11 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== +quanmsms@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/quanmsms/-/quanmsms-1.0.2.tgz#8e7748329f87fd5f5550fe8eb94b6ab11a54ff90" + integrity sha512-wY4A2tz5ZANlgJw4t3fTgmcRpXO6FkyAxSfipdWa8DZxtfbItjQ4BErlugiEmL0sB2cTwJG9P3w5NT7i56T11Q== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"