循序渐进BootstrapVue,开发公司门户网站(3)--- 结合邮件发送,收集用户反馈信息
在我们公司门户网站里面,如果有需要,我们可以提供一个页面给用户反馈信息,以便获得宝贵的用户信息反馈或者一些产品咨询的记录,一般这个结合邮件发送到负责人的邮箱即可。本篇随笔结合后端发送邮件的操作,把相关信息发送到门户网站的负责人邮箱里面。
1、客户反馈界面
我们这个主题主要介绍BootstrapVue的使用,虽然我们有时候使用了常规的HTML元素,不过也是使用了Bootstrap的样式来处理界面的。
本篇随笔继续介绍BootstrapVue中的表单组件 b-form 及表单元素的使用。在线反馈界面如下所示。

在这里主要通过一些常规的数据录入获得客户的反馈即可。
Vue模板的HTML界面代码如下所示
<b-form @submit="onSubmit" class="mt-4 mb-5">
<b-form-group id="input-group-1" label-for="input-1" class="mb-4">
<b-form-input id="input-1" v-model="form.name" required placeholder="请输入您的姓名"></b-form-input>
</b-form-group> <b-form-group id="input-group-2" label-for="input-2" class="mb-4">
<b-form-input id="input-2" v-model="form.phone" required placeholder="请输入您的手机/邮箱"></b-form-input>
</b-form-group> <b-form-group id="input-group-3" label-for="input-3" class="mb-4">
<b-form-select id="input-3" v-model="form.suggest" placeholder="反馈类型" :options="suggest" required></b-form-select>
</b-form-group> <b-form-group id="input-group-4" label-for="input-3" class="mb-5">
<b-form-textarea id="input-4" v-model="form.message" required rows="5" placeholder="请输入您想说的话"></b-form-textarea>
</b-form-group> <b-button type="submit" block variant="info">提 交</b-button>
</b-form>
而其中data里面定义了表单对应的数据,如下所示
form: {
name: '',
phone: '',
suggest: null,
message: '',
},
suggest: [
{ value: null, text: '反馈类型' },
{ value: '需求上报', text: '需求上报' },
{ value: '商务洽谈', text: '商务洽谈' },
{ value: '意见建议', text: '意见建议' },
{ value: '其它', text: '其它' }
],
在数据提交的时候,我们根据正则表达式来判断一下对应的数据,当然我们也可以使用BootstrapVue的表单验证控件来处理,具体可以参考BootstrapVue的表单验证组件。
async onSubmit (evt) {
evt.preventDefault()
const phoneReg = /^1[3456789]\d{9}$/
const emailReg = /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
if (!phoneReg.test(this.form.phone) && !emailReg.test(this.form.phone)) {
this.$bvToast.toast(`提交失败,请输入正确的手机号或邮箱号`, {
title: '提交结果',
variant: 'danger',
autoHideDelay: 5000
})
return
}
而其中 this.$bvToast.toast 使用了BootstrapVue 冒泡提示组件。
通过this.$bvToast.toast()Vue组件实例注入从应用程序中的任何位置生成动态toast,而无需在应用程序中放置<b-toast>组件。
使用this.$bvToast.toast()方法生成toasts。该方法接受两个参数:
message: toast主体的内容(字符串或VNodes数组)。必填的。将不会显示带有空消息的Toasts。有关将VNodes数组作为消息传递的示例,请参阅Advanced usage部分。options: 用于提供标题和/或附加配置选项的可选选项对象。title选项可以是字符串或VNodes数组
options参数接受<b-toast>组件以camelCase name格式而不是kebab case格式接受的大多数道具(static和visible的除外)。
接着我们收集客户的信息,组合后调用后端发送邮件接口,发送邮件即可,最后提示用户发送是否成功。
var type = '反馈'
var html = `
<p><strong>发信人姓名:</strong></p>
<p>${this.form.name}</p>
<p><strong>发信人联系方式:</strong></p>
<p>${this.form.phone}</p>
<p><strong>发信人反馈类型:</strong></p>
<p>${this.form.suggest}</p>
<p><strong>发信人留言:</strong></p>
<p>${this.form.message}</p>
`
const flag = SendMail(html, type) if (flag) {
this.form = {
name: '',
phone: '',
message: ''
}
this.$bvToast.toast(`提交成功,我们将尽快与您取得联系!`, {
title: '提交结果',
variant: 'success',
autoHideDelay: 5000
})
} else {
this.$bvToast.toast(`提交失败,请稍后重试!`, {
title: '提交结果',
variant: 'danger',
autoHideDelay: 5000
})
}
2、邮件的发送处理
关于邮件的发送,之前有参考过 nodemailer,这个使用node环境发送邮件的组件,不过我们现在的BootstrapVue项目的前端不符合这个条件,除非引入 nuxt ,让页面先在后端运行再推送给前端展示。
关于nodemailer的学习,可以参考下:https://github.com/nodemailer/nodemailer,或者官网:https://nodemailer.com/about/
它的使用代码如下所示:
"use strict";
const nodemailer = require("nodemailer"); // async..await is not allowed in global scope, must use a wrapper
async function main() {
// Generate test SMTP service account from ethereal.email
// Only needed if you don't have a real mail account for testing
let testAccount = await nodemailer.createTestAccount(); // create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "smtp.ethereal.email",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: testAccount.user, // generated ethereal user
pass: testAccount.pass, // generated ethereal password
},
}); // send mail with defined transport object
let info = await transporter.sendMail({
from: '"Fred Foo " <foo@example.com>', // sender address
to: "bar@example.com, baz@example.com", // list of receivers
subject: "Hello ", // Subject line
text: "Hello world?", // plain text body
html: "<b>Hello world?</b>", // html body
}); console.log("Message sent: %s", info.messageId);
// Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com> // Preview only available when sending through an Ethereal account
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
// Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
}
不过前面说了,我们不使用这个,就一笔带过,谈谈我们后端使用ABP接口发送邮件的处理吧。
我们前端封装一个调用后端接口发送邮件的通用处理函数,如下所示。
function privateSendEmail(email, subject, body) {
var data = {
email,
subject,
body
}
return request({
url: '/abp/services/app/Account/SendEmail',
method: 'post',
data: data
})
}
再简单封装一下发送反馈信息的邮件操作函数,如下所示。
export async function SendMail(html, type) { //发送邮件
type = type || '反馈'
const mailOptions = {
from: `一条来自【广州爱奇迪】网站的${type} wuhuacong@163.com`,
to: 'wuhuacong@163.com',
subject: `一条来自【广州爱奇迪】网站的${type}`, //邮件标题
html, //邮件内容
var email = 'wuhuacong@163.com'
var subject = `一条来自【广州爱奇迪】网站的${type}`
var result = false
await privateSendEmail(email, subject, html).then(data => {
result = data.success
return result
})
}
这样我们在组件里面,直接引入这个封装函数进行调用即可。
import { SendMail } from '@/api/system/mail'
最后发送操作。

再次回到后端的ABP邮件发送接口上,我之前在随笔《循序渐进VUE+Element 前端应用开发(33)--- 邮件参数配置和模板邮件发送处理》中介绍过邮件发送的操作,我们ABP框架后端是基于AbpMailkitModule组件进行发送邮件的,只需要配置好相关发送邮件的信息即可。

Module中初始化中处理下对应的自定义发送和自定义配置项的处理类。

然后在使用的应用服务类中注入对应的邮件发送接口以供使用。

我们简单定义一个发送邮件的DTO对象,用来接收来自客户的反馈信息,如下所示。
/// <summary>
/// 常规邮件信息
/// </summary>
public class SendEmailDto
{
[Required]
[MaxLength(AbpUserBase.MaxEmailAddressLength)]
public string Email { get; set; } /// <summary>
/// 内容
/// </summary>
[Required]
public string Body { get; set; } /// <summary>
/// 标题
/// </summary>
[Required]
public string Subject { get; set; } }
最后直接发送邮件处理即可。
/// <summary>
/// 发送常规邮件内容
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task SendEmail(SendEmailDto input)
{
await _emailSender.SendAsync(new System.Net.Mail.MailMessage
{
To = { input.Email },
Subject = input.Subject,
Body = input.Body,
IsBodyHtml = true
}); LogHelper.Logger.Info($"校验邮件发送给:{input.Email}, 发送邮件成功");
}
发送处理后,我们就会在邮箱中收到邮件信息,如下所示。

以上只是简单对用户信息进行收集,我们如果在系统各种常规的处理中,也可以通过邮件和系统用户进行信息通知,如找回密码、更新密码,重要操作、工作提醒通知等等操作。
循序渐进BootstrapVue,开发公司门户网站(3)--- 结合邮件发送,收集用户反馈信息的更多相关文章
- 循序渐进BootstrapVue,开发公司门户网站(5)--- 使用实际数据接口代替本地Mock数据
在我们开发一些门户网站功能的时候,有时候我们需要快速的创建数据模型来进行数据展示,因为数据结构可能处于不断的修正变化之中,因此服务端的接口我们可以暂时不开发,当我们基本完成数据结构和界面展示的时候,就 ...
- 循序渐进BootstrapVue,开发公司门户网站(1)---基于Bootstrap网站模板构建组件界面
在前面随笔<使用BootstrapVue相关组件,构建Vue项目界面>概括性的介绍了BootstrapVue的使用过程,其实选用这个主要就是希望能够用来构建一些公司门户网站的内容,毕竟基于 ...
- 循序渐进BootstrapVue,开发公司门户网站(2)--- 使用wow.js动画组件以及自定义的CSS样式处理动态效果
在我们开发的页面中,让页面有一些动画效果,可以让页面更加有吸引力,只要不是处理太过,一般人还是希望有一些动态效果,如滚动动画加载,悬停处理变化等效果,本篇随笔介绍使用wow.js动画组件以及自定义的C ...
- 循序渐进BootstrapVue,开发公司门户网站(6)--- 门户网站后端内容管理
我们在做门户网站的时候,如果网站的内容可以动态从后端进行管理,那么调整网站内容就非常方便,有时候如一些公司新闻.产品信息.轮播广告信息等都需要动态调整的,有一个方便的后端内容管理是非常方便的.本篇随笔 ...
- 循序渐进BootstrapVue,开发公司门户网站(4)--- 使用b-carousel-slide组件实现图片轮播以及vue-awesome-swiper实现图片滑动展示
在BootstrapVue组件库里面,提供了很多对Bootstrap同等类似的组件封装,其中图片轮播可以采用b-carousel-slide组件实现,而有一些小的图片,如客户/合作伙伴Logo或者友情 ...
- 基于Vue开发的门户网站展示和后台数据管理系统
基于Vue的前端框架有很多,这几年随着前端技术的官方应用,总有是学不完的前端知识在等着我们,一个人的精力也是有限,不可能一一掌握,不过我们学习很大程度都会靠兴趣驱动,或者目标导向,最终是可以以点破面, ...
- 基于SqlSugar的开发框架循序渐进介绍(6)-- 在基类接口中注入用户身份信息接口
在基于SqlSugar的开发框架中,我们设计了一些系统服务层的基类,在基类中会有很多涉及到相关的数据处理操作的,如果需要跟踪具体是那个用户进行操作的,那么就需要获得当前用户的身份信息,包括在Web A ...
- C#-MVC开发微信应用(7)--在管理系统中同步微信用户分组信息
在前面几篇文章中,逐步从原有微信的API封装的基础上过渡到微信应用平台管理系统里面,逐步介绍管理系统中的微信数据的界面设计,以及相关的处理操作过程的逻辑和代码.希望从一个更高的层次介绍微信的开发. 在 ...
- (转)转一份在 51testing 上的讨论——如何测试一个门户网站是否可以支持10万用户同时在线?
转自:http://www.cnblogs.com/jackei/archive/2006/11/16/561846.html 这个帖子的内容比较典型,大家有兴趣可以也思考一下. 先是楼主提出问题: ...
随机推荐
- 视频格式mkv、mp4、avi、flv、mov、wmv、webm特点和区别
mkv是一种多媒体封装格式,这个封装格式可把多种不同编码的影像及 16 条或以上不同格式的音频和语言不同的字幕封装到一个 Matroska Media 档内. 它也是其中一种开放原始码的多媒体封装格式 ...
- MSSQL·查看数据库编码格式
阅文时长 | 0.67分钟 字数统计 | 837.6字符 主要内容 | 1.引言&背景 2.声明与参考资料 『MSSQL·查看数据库编码格式』 编写人 | SCscHero 编写时间 | 20 ...
- golang:正则表达式总结
正则表达式是一种进行模式匹配和文本操纵的复杂而又强大的工具.虽然正则表达式比纯粹的文本匹配效率低,但是它却更灵活.按照它的语法规则,随需构造出的匹配模式就能够从原始文本中筛选出几乎任何你想要得到的字符 ...
- [bug] MapReduce卡死
参考 https://blog.csdn.net/WYpersist/article/details/80202055
- [Python] Tkinter command
例1:创建按钮 import tkinter as tk class App: def __init__(self,root): frame = tk.Frame(root) frame.pack() ...
- [笔记] 《我的第一本c++书》
函数 优秀函数的五个要点 函数的返回值:直接返回和间接返回(指针) 在函数的入口处对参数有效性进行检验:if语句,断言(assert) 如果函数有返回值,不可返回一个指向函数体内局部对象的指针或引用 ...
- 搞清楚 硬件环境 os环境 网络环境 搞清楚测试工具 测试步骤 自己搭测试环境 自测
1,遇事的第一反应要从变化情绪转变为做出判断.判断什么?判断这一件事对自己是否重要,是否关乎我的个人利益,是否影响我的人际关系等等等等.如果答案都是否,那就没必要着急忙慌了.如果答案是是 冷静,其实是 ...
- shell基础之函数
shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数.给这段代码起个名字称为函数名,后续可以直接调用该段代码. 格式: func() { #指定函数名 command # ...
- 041.Python守护进程,锁信号量和事件
一 守护进程 1.1 基本概念 守护进程 正常情况下,主进程默认等待子进程调用结束之后结束 守护进程在主进程执行代码结束后,自动终止 守护进程语法: 进程对象.daemon = True ,设置该进程 ...
- linux基础之进阶命令二
本节内容 基础命令二: 1. alias:查看和设置别名(alias:别名) alias 'ren=ls -ld' \ren 可不取消别名,执行ren原本的命令 2. unalia ...