在当今的营销环境中,提供出色的客户服务对于确保客户满意度和忠诚度至关重要。企业经常使用票务系统来管理客户查询,投诉和请求。这些解决方案不仅巩固了客户支持互动,还允许快速发行跟踪和解决方案。
AppWrite,一种广泛的开源后端服务器和API Suite,为开发人员提供了一个可靠的框架,用于开发各种应用程序。由于其庞大的功能设置和易于集成,它是开发客户支持票务应用程序的绝佳选择,可改善服务交付和整体客户体验。
在本文中,我们将使用AppWrite Cloud构建客户支持票务应用程序,以提供实时更新,存储和渲染数据以及一个开源设计系统 - Pink Design,以设置应用程序。<<<<<<<<<<< /p>
github
该项目的完整源代码位于here。克隆并分叉它开始。
先决条件
要与本教程一起,需要以下内容:
入门
项目设置和安装
在终端中运行以下命令以创建一个新的nuxt.js应用程序:
npx nuxi init <project-name>
导航到项目目录并安装所需的依赖项。
cd <project-name>
npm install
运行npm run dev
在我们的浏览器中在https://localhost:3000/上启动开发服务器。
注意:上面的
<project-name>
代表我们的应用程序的名称;随时可以称呼它。
安装AppWrite和粉红色设计
什么是AppWrite?
Appwrite是一个开发平台,可为Web和移动应用程序构建后端服务器提供功能强大的API和管理控制台。
什么是粉红色设计?
Pink Design是AppWrite的开源设计系统,用于创建一致且可重复使用的用户界面。粉红色设计旨在强调协作,开发人员的经验和可访问性。
要在我们的NUXT.JS应用程序中使用AppWrite,请安装AppWrite的客户端SDK(软件开发套件)和粉红色设计。
npm install appwrite
npm install @appwrite.io/pink
设置appwrite云
登录到Appwrite Cloud并创建一个新项目。
新项目将出现在控制台上。接下来,复制项目ID 。我们将使用此设置我们的nuxt.js应用程序。
创建数据库,集合,属性,并添加示例数据
导航到数据库选项卡,然后单击创建数据库按钮以创建一个新的数据库。
接下来,我们将通过单击创建集合按钮来创建数据库中的集合。给它一个合适的名称,然后单击创建。
转到更新权限 设置的部分页面。我们希望将CRU访问(创建,读取,更新)具有角色:我们创建的集合的任何值。我们可以稍后自定义这些角色,以指定谁可以访问或写入我们的数据库。
导航到属性选项卡,并为我们的集合创建一组属性,如下所示:
属性键 | 属性类型 | 大小 | 元素 | 必需 |
---|---|---|---|---|
电子邮件 | 电子邮件 | null | nil | 否 |
请求 | 字符串 | 2000 | nil | 是 |
名称 | 字符串 | 256 | nil | 是 |
状态 | 字符串 | 256 | nil | 否 |
我们需要为应用程序添加示例数据。为此,请前往文档部分,然后单击创建文档,然后将模型添加到集合中,如下所示:
将AppWrite与NUXT.JS集成
让我们创建一个表格来接受客户支持请求。为此,请在项目的根文件夹中创建一个pages/index.vue
文件,并在下面添加以下语法:
// pages/index.vue
<template>
<div>
<nav class="u-flex u-cross-center u-main-space-between u-padding-32">
<h2 class="logo u-padding-16 eyebrow-heading-1 u-color-text-pink">
<NuxtLink to="/">PINK CUSTOMER SUPPORT</NuxtLink>
</h2>
<NuxtLink to="/requests">
<span class="button"> SUPPORT REQUESTS</span>
</NuxtLink>
</nav>
<form @submit.prevent="submitForm">
<h2 class="eyebrow-heading-1 u-text-center u-padding-64">
write a request
</h2>
<div class="u-grid u-cross-center u-main-center u-padding-16">
<label for="email">Full Name:</label>
<input placeholder="Full Name" type="text" id="name" v-model="name" required />
<label for="email">Email:</label>
<input placeholder="Email" type="email" id="email" v-model="email" required />
<label for="request">Request:</label>
<textarea class="input-text" placeholder="Request" type="text" id="request" v-model="request" required />
<button class="button" type="submit">
<span class="text">Submit</span>
</button>
</div>
</form>
</div>
</template>
下图显示了应用上述配置后我们的应用程序的外观。
在pages/index.vue
文件中,我们将为我们提交的每个客户支持请求中的AppWrite数据库中创建一个新文档。在下面复制并粘贴代码段:
// pages/index.vue
<script>
import { Client, Databases, ID } from "appwrite";
export default {
data() {
return {
name: "",
email: "",
request: "",
};
},
methods: {
async submitForm() {
const client = new Client();
const databases = new Databases(client);
client
.setEndpoint("OUR_API_ENDPOINT") // Your API Endpoint
.setProject("OUR_PROJECT_ID"); // Your project ID
try {
const response = await databases.createDocument(
"OUR_DATABASE_ID",
"OUR_COLLECTION_ID",
ID.unique(),
{
name: this.name,
email: this.email,
request: this.request,
status: "open",
}
);
console.log(response);
this.name = "";
this.email = "";
this.request = "";
} catch (error) {
console.error(error);
}
},
},
};
</script>
上面的代码段进行以下操作:
- 从表单输入中获取数据值
- 每当提交表单
- 将表格重置为其默认状态
提取客户支持请求
我们还需要显示我们之前提交的客户支持请求。为此,使用以下语法在项目的根文件夹中创建一个components/FetchDocuments.js
文件:
// components/FetchDocuments.js
<script setup>
import { Client, Databases } from "appwrite";
const client = new Client();
const databases = new Databases(client);
client
.setEndpoint("OUR_API_ENDPOINT") // Your API Endpoint
.setProject("OUR_PROJECT_ID"); // Your project ID
export const FetchDocuments = databases.listDocuments( "OUR_DATABASE_ID", "OUR_COLLECTION_ID");
让我们分解上面的代码段:
- 导入所需的模块客户和数据库
- 为模块创建一个新实例
注意:获取
API Endpoint
,Project ID
,[DATABASE_ID]
和
来自AppWrite的控制台的[COLLECTION_ID]
然后,创建一个pages/request.vue
文件,导入名为FetchDocuments
的实例,该实例通过在安装组件时获取请求与AppWrite Services进行交互。我们还必须仅通过AppWrite数据库的客户电子邮件渲染请求。
// pages/request.vue
<script>
import { FetchDocuments } from "@/components/FetchDocuments.js";
export default {
data() {
return {
docs: [],
};
},
async mounted() {
const response = await FetchDocuments;
const data = response.documents.slice().reverse();
// Filter the data array and push values that serve as the beginning of a support request to the docs variable
data.filter((item) => {
if (item.email !== null) {
this.docs.push(item);
}
});
},
};
</script>
pages/request.vue
文件中的渲染请求也将按降序降序,最新请求位于顶部。
//pages/request.vue
<template>
<main>
<nav>
... // nav bar
</nav>
<div class="container">
<h2 class="eyebrow-heading-1 u-text-center u-padding-64">support requests</h2>
<ul class="list">
<li class="box" v-for="doc in docs" :key="doc.$id">
<div class="u-flex u-cross-center u-main-space-between">
<div class="u-grid">
<div class="u-flex u-cross-center u-main-space-between">
<span class="text eyebrow-heading-1"> {{ doc.name }} </span>
<div class="tag">
<span class="icon-check-circle" aria-hidden="true"></span>
<span class="text">{{ doc.status }}</span>
</div>
</div>
<span class="text">{{ doc.request.slice(0, 200) }}</span>
</div>
<NuxtLink :to="`/request/${doc.$id}`">
<span class="button icon-cheveron-right" aria-hidden="true"></span>
</NuxtLink>
</div>
</li>
</ul>
</div>
</main>
</template>
应用上述配置后,应用程序将看起来像这样:
访问单个客户支持请求
在这里,为了查看单个请求及其内容,创建一个pages/request/[id].vue
文件并添加以下语法:
//pages/request/[id].vue
<template>
<div class="u-flex u-cross-center u-main-space-between u-padding-32">
<h2 class="eyebrow-heading-1 u-text-left u-padding-32">
CUSTOMER: {{ customer.name }}
</h2>
</div>
<div class="u-grid">
<h2 class="u-x-small u-bold u-text-right u-margin-inline-start-32">
{{ new Date(customer.$createdAt) }}
</h2>
<p class="text u-normal u-text-right u-padding-32">
{{ customer.request }}
</p>
</div>
</template>
<script>
import { useRouter, useRoute } from "vue-router";
import { Client, Databases, ID } from "appwrite";
import { FetchDocuments } from "@/components/FetchDocuments";
export default {
data() {
const router = useRouter();
const isIdMatch = router.currentRoute.value.params.id;
return {
requestId: isIdMatch,
request: "",
docs: [],
customer: [],
};
},
async mounted() {
const client = new Client();
const databases = new Databases(client);
client
.setEndpoint("OUR_API_ENDPOINT") // Your API Endpoint
.setProject("OUR_PROJECT_ID"); // Your project ID
// Instance to fetch a customer's name
const singleDocument = await databases.getDocument(
"OUR_DATABASE_ID",
"OUR_COLLECTION_ID",
`${this.requestId}`
);
this.customer = singleDocument;
},
</script>
上面的代码语法执行以下操作:
- 获取当前页面路由ID
- 每当安装组件时,使用现有路由ID来初始化一个实例以获取客户名称
添加评论
在pages/request/[id].vue
文件中,我们需要获取单个请求内容,并创建一个印象,客户可以对他/她较早提出的请求发表评论。对于评论功能,让我们创建一个表格来提交评论。我们还想在请求的状态下更改该请求的状态。
//pages/request/[id].vue
<template>
<div>
// customer name
<form @submit.prevent="updateForm">
<div class="u-grid u-cross-center u-main-center u-padding-32">
<span style="font-size: 20px" class="u-color-text-pink">
Has this issue been resolved?
</span>
<div class="checkbox">
<label for="status1">Yes:
<input type="radio" v-model="status" id="checkbox1" value="resolved"/>
</label>
<label for="status2">No:
<input type="radio" v-model="status" id="checkbox2" value="open" />
</label>
</div>
<label for="request" style="font-size: 20px" class="u-color-text-pink">
If not, state what the current issue is:
</label>
<textarea class="input-text" placeholder="Comment" type="text" id="request" v-model="request" required />
<button class="button" type="submit">
<span class="text">Add Comment</span>
</button>
</div>
</form>
</div>
</template>
<script>
export default {
data() {
return {
request: "",
status: "",
docs: [],
};
},
// ... Fetch customer's name
methods: {
async updateForm() {
const client = new Client();
const databases = new Databases(client);
client
.setEndpoint("OUR_API_ENDPOINT") // Your API Endpoint
.setProject("OUR_PROJECT_ID"); // Your project ID
try {
const response = await databases.createDocument(
"OUR_DATABASE_ID",
"OUR_COLLECTION_ID",
ID.unique(),
{
request: this.request,
status: this.status,
email: null,
name: this.requestId,
}
);
this.docs.push(response);
this.request = "";
} catch (error) {
console.error(error);
}
},
},
}
上面的代码语法执行以下操作:
- 发布一个新文档,作为对AppWrite数据库的评论
- 创建一个将请求状态更改为
open
或resolved
的选项
- 该文档还名称为当前路由ID访问它。
- 将新文档推到数据变量
docs
;然后将新文档作为评论,以给人以实时更新的印象 - 重置表格
然后,我们将在pages/request/[id].vue
文件中初始化一个实例,以获取客户的请求和评论。我们还希望仅在注释名称或请求ID与当前路线匹配时才呈现客户的请求和评论。
//pages/request/[id].vue
<template>
<div>
// customer's request and previous comments
<ul class="list">
<li v-for="doc in docs" :key="doc.$id">
<div class="u-flex u-cross-center u-main-space-between">
<h2 class="u-x-small u-bold u-text-right u-margin-inline-start-32">
{{ new Date(doc.$createdAt) }}
</h2>
</div>
<div class="u-grid">
<p class="text u-normal u-text-right u-padding-32">{{ doc.request }}</p>
</div>
</li>
</ul>
</div>
</template>
<script>
async mounted() {
// ... Fetch customer's name
// Instance to fetch a customer's request and comments
const comments = await FetchDocuments;
const MatchComments= comments.documents;
MatchComments.filter((item) => {
if (item.name === this.requestId || item.$id === this.requestId) {
this.docs.push(item);
}
});
}
</script>
在应用上面的配置之后,这是该应用程序的外观演示:
结论
这篇文章演示了AppWrite Cloud的实时功能,以使用开源设计系统来存储和更新数据和样式的客户支持票务应用程序。将用户身份验证集成在应用程序中也是AppWrite的功能之一,该功能是帮助识别和验证访问该应用程序的用户身份的工具。
资源
这些资源也可能有帮助: