Skip to content
This repository has been archived by the owner on Jul 7, 2022. It is now read-only.

Commit

Permalink
Merge branch 'dev' of github.com:swordCodePractice/InternetQuestionBank
Browse files Browse the repository at this point in the history
  • Loading branch information
seho-dev committed Jun 6, 2021
2 parents 5eea220 + ca01329 commit e1fc1bd
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 54 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,14 @@ uniCloud.callFunction({
- [前端面试 3+1 开源题库](https://github.com/haizlin/fe-interview)
- [Guide 哥的 JAVA 题库](https://github.com/Snailclimb/JavaGuide)
- [达达前端](https://github.com/webVueBlog/interview-answe)
- [凌枫-phpQ&A-授权中...](https://github.com/colinlet/PHP-Interview-QA)

- [凌枫-phpQ&A](https://github.com/colinlet/PHP-Interview-QA)
- [PHP interview best practices in China](https://github.com/wudi/PHP-Interview-Best-Practices-in-China)
# QQ 群和钉钉群欢迎大家加入

<img width="30%" src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-c7e81452-9d28-4486-bedc-5dbf7c8386a5/6f5b6587-8efe-400f-8fcb-f277892a9854.png" />
<img width="32%" src="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-c7e81452-9d28-4486-bedc-5dbf7c8386a5/309debe7-7f2a-47ae-a415-875e5b1f4922.jpg"></img>

其他渠道联系我们:[联系我们](https://www.yuque.com/docs/share/92cb643e-b6a4-4dd9-8cb4-224556e4ccef)
# 许可

Apache License © 剑指题解
Expand Down
60 changes: 23 additions & 37 deletions install.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
- [Github 仓库](https://github.com/swordCodePractice/InternetQuestionBank)
- [码云 仓库](https://gitee.com/yinzhuoei/InternetQuestionBank)
## 简要概览
`剑指题解` 作为一款完全使用 [uniapp](https://uniapp.dcloud.io/) 跨端开发,配合 [UniCloud](https://unicloud.dcloud.net.cn/login) 云函数,非常轻量级,无需购买服务器设备,云函数与数据库真正做到一键部署。一键部署上线。
剑指题解作为一款完全使用 [uniapp](https://uniapp.dcloud.io/) 跨端开发,配合 [UniCloud](https://unicloud.dcloud.net.cn/login) 云函数,非常轻量级,无需购买服务器设备,云函数与数据库真正做到一键部署。一键部署上线。如果你不熟悉uniapp或者unicloud那么就要去自行学习这部分的知识


开源的意义在于,让更多的人,用到我们这款题库提升自己的市场价值,也能在此基础上,自定义你想要的功能造福更多的人。
Expand All @@ -22,18 +22,16 @@
- 如果你是macos系统,那么请注意,您必须本地的node环境要>10,且需要配置hbulderX运行的node环境必须是本地的node(hbuilderx有自带的低版本node,我们不能使用低版本的node),那么如何设置hbuilderx的node版本呢,打开hbuilderx -> 偏好设置 -> 运行配置 -> 设置node启动为本地的node即可。


```javascript
```shell
# 拉取最新代码
git clone https://github.com/swordCodePractice/InternetQuestionBank

cd InternetQuestionBank

# 安装项目依赖
npm install
```


在注册账号后,请先在[Dcloud个人后台](https://dev.dcloud.net.cn/)进行 `账户中心`- `个人实名认证` 完成认证,否则无法创建云服务空间。
在注册Dcloud账号后,请先在[Dcloud个人后台](https://dev.dcloud.net.cn/)进行 `账户中心`- `个人实名认证` 完成认证,否则无法创建云服务空间。


**手机号和邮箱均需要做验证后,方可操作**
Expand Down Expand Up @@ -79,7 +77,13 @@ npm install
如果执行后,如果在 [云管理平台](https://unicloud.dcloud.net.cn/) 数据库页面,未发现表结构,请在 `database/db_init` 文件上右键,点击 `初始化云数据库` 进行手动初始化。


**注意:`敏感词过滤模块` 为付费模块,可以测试的时候试用七天,在测试部署的时候,申请试用即可。**
### 如何运行程序?
剑指题解项目使用了uniapp的cli创建方式,基于vue3,但是截止写这篇文档的时候,脚手架的一个依赖在mac环境下报错导致运行程序失败:
```shell
/InternetQuestionBank/node_modules/fork-ts-checker-webpack-plugin-v5/node_modules/fs-extra/lib/mkdirs/make-dir.js:85
```
我在这里把对应的issue贴一下:[如何解决这个问题?](https://github.com/swordCodePractice/InternetQuestionBank/issues/16)
**如果你不是mac系统你不需要做这一步**
### 运行到微信开发者工具


Expand All @@ -106,15 +110,15 @@ npm install
[unicloud小程序域名配置](https://uniapp.dcloud.io/uniCloud/quickstart?id=%e5%b0%8f%e7%a8%8b%e5%ba%8f%e4%b8%ad%e4%bd%bf%e7%94%a8unicloud%e7%9a%84%e7%99%bd%e5%90%8d%e5%8d%95%e9%85%8d%e7%bd%ae)


## 云函数开发
云函数技术栈使用的是explain.js以及ts,我们在后端开发云函数的时候,需要经过以下工具进行辅助:
## 二次云函数开发
**如果你想对本项目的后端提交pr或者你想要二次开发,那么这个部分对你很有帮助**
云函数技术栈使用的是explain框架以及ts,我们在后端开发云函数的时候,需要经过以下工具进行辅助:

1. 全局安装typescript
1. 全局安装nodemon
1. 全局安装esbuild-node-tsc



具体看以下之前写的教程:
[使用TS开发云函数指南](https://www.yinzhuoei.com/index.php/archives/470/)

Expand All @@ -123,46 +127,28 @@ npm install
npm run dev
```
![image.png](https://cdn.nlark.com/yuque/0/2021/png/710380/1618035605323-1fe45eea-62a2-48fa-9e57-90c7eb16b6c6.png#align=left&display=inline&height=818&margin=%5Bobject%20Object%5D&name=image.png&originHeight=818&originWidth=962&size=108475&status=done&style=none&width=962)
出现编译成功之后,我们就可以上传云函数啦!

本地开发环境开启成功之后,我们就可以使用ts迭代我们的后端逻辑并且保存之后点击云函数上传即可。

## 自定义配置
在项目源代码中,有部分代码并没有上传(涉及到账号密码之类的),在这里整理一下:


1.云函数公共模块下的uni-id,缺少config.json,这里提供一个示例,如果需要额外配置,请阅读uni-id文档:
```json
{
"passwordSecret": "PyFZVwsT9QVXoeeh",
"tokenSecret": "LCMsnrTFpsYmHyC4",
"tokenExpiresIn": 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999,
"bindTokenToDevice": false,
"passwordErrorLimit": 5,
"tokenExpiresThreshold": 600,
"passwordErrorRetryTime": 3600
}
```
在项目源代码中,有部分代码并没有上传(涉及到账号密码),如果你要完整的开发小程序,那这一步请认真阅读:
随着项目的迭代,后端开发需要配置很多很多的config,我们都在gitignore里注明了。

后端自定义配置说明请移步到:[语雀-安装配置项指南](https://www.yuque.com/docs/share/9ea0a6a6-7af6-4c6d-8679-838e212c9ac0)

2.关于敏感词过滤模块,小程序用户建议使用微信官方的敏感词调用,官方是免费的且准确的,小程序后期的feature也会更换成微信官方的。
## 云自助配置

部分云函数是需要用户自己到云后台配置,代码中没办法体现,但是我们仍然贴心的准备了一份指南文档,帮助用户更好的上手。
请移步:[语雀-安装配置项指南](https://www.yuque.com/docs/share/f500ddaa-6a1e-4449-84d6-908564e27de9)

3.自助拉取题的函数“pull”, 如果你完成了上面的云函数部署,你能在后台看到一个函数叫做“pull”,这个函数是我们的设计,调用一次这个函数会去我们合作的开源项目拉取最新的题到我们的数据库,这个功能我们后期版本可能会不对外开放。但是在这里教大家如何设置这个云函数,如果你不需要这个自动拉取题库的函数,那就删除掉它。


![image.png](https://cdn.nlark.com/yuque/0/2021/png/710380/1618036667246-b0248c84-1a0d-43ee-b240-35ee244d6671.png#align=left&display=inline&height=976&margin=%5Bobject%20Object%5D&name=image.png&originHeight=976&originWidth=2039&size=75929&status=done&style=none&width=2039)
我们设置每天早上8点执行一遍拉取函数:
```json
[
"cron:0 0 8 * * *"
]
```
## 常见问题


- `当前登录账户需完成手机号验证后才可上传云函数`
- 请先完成uni-cloud 账户管理中心的手机号和邮箱验证!
- `[error] IDE service port disabled.`
- 参考 微信开发者工具开启服务端口
- `[error] Error: Fail to open IDE` 
- 尝试在微信开发者工具, `项目` - `重新打开此项目` 

## 联系我们
您遇到的问题不在上面?那请[联系我们吧~](https://www.yuque.com/docs/share/92cb643e-b6a4-4dd9-8cb4-224556e4ccef)
15 changes: 11 additions & 4 deletions src/api/search.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import callFunction from "../common/callFunction";
import { arrObjectUnique } from "../util/common";
const db = uniCloud.database();

/**
Expand Down Expand Up @@ -71,14 +72,20 @@ export async function addSearchLog(params:{
export async function getHotSearchWordList(): Promise<ActionResult> {
return new Promise((resolve) => {
db.collection("opendb-search-hot")
.orderBy("create_date", "desc")
.orderBy("count", "desc")
.get()
.aggregate()
.sort({
create_date: -1,
count: -1
})
.skip(0)
.limit(50)
.end()
.then((res) => {
const { success, result } = res;
// 循环热搜结果,根据content去重复
resolve({
success,
data: result.data,
data: arrObjectUnique(result.data, "content").slice(0, 15),
});
})
.catch((err: { message: string }) => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/question/writeQuestion.vue
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export default defineComponent({
const checkResult = await checkContentSecurity({
content: html
})
if(checkResult.success && !checkResult.data){
if(checkResult.success && !checkResult.result){
// 如果校验失败,则提示
uni.hideLoading();
uni.showToast({
Expand Down
6 changes: 4 additions & 2 deletions src/pages/search/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</view>
<view class="search-body" v-if="!associativeShow">
<!-- 搜索历史 -->
<view class="word-container" v-if="localSearchList.length">
<view class="word-container" v-if= "localSearchList.length">
<view class="word-container_header">
<text class="word-container_header-text">搜索历史</text>
<i-icon
Expand Down Expand Up @@ -149,7 +149,9 @@ export default {
} else {
// ++页数并且进行调用搜索
this.associativeConfig.page++;
this.handleSearch();
this.handleSearch({
pagination: true
});
}
}
},
Expand Down
14 changes: 13 additions & 1 deletion src/util/common.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
export const removeHtmlTag = (htmlStr: string) => {
return htmlStr.replace(/<[^>]+>/gi, "");
};

// 对象数组去重
export const arrObjectUnique = (arr: any[], key: string) => {
const temp = {};
for(let k in arr){
if(arr[k][key] && !temp[arr[k][key]]){
temp[arr[k][key]] = arr[k];
}
}
return Object.values(temp);
}

// 数组去重
export const arrUnique = (arr) => {
export const arrUnique = (arr: any[]) => {
for (let i = arr.length - 1; i >= 0; i--) {
const curIndex = arr.indexOf(arr[i]);
const lastIndex = arr.lastIndexOf(arr[i]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,19 @@ namespace CertificationApplyOrder {
.then(async () => await this.handler("updateCertificationApplyOrderState"))
.catch((err) => err);
}
// 申请单列表分页查询
async getCertificationApplyOrder(){
return handleMustRequireParam(
[
{
key: "state",
value: "状态",
}
],
this.event.params
)
.then(async () => await this.handler("getCertificationApplyOrder"))
.catch((err) => err);
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,41 @@ namespace CertificationApplyOrderService {
this.userID = data.context.userID;
this.nowDate = new Date().toISOString();
}
async getCertificationApplyOrder(params: {
limit: number;
page: number;
state: number;
}) {
const { limit = 10, page = 1, state } = params;
const whereParams = {
state,
};
const data = await collection
.where(whereParams)
.skip(limit * (page - 1))
.limit(limit)
.sort({
createTime: -1,
})
.filed(`state, userID, content, createTime`)
.get();
const countResult = await collection.where(whereParams).count();
return {
list: data.data,
count: countResult.total,
};
}
async addCertificationApplyOrder(params: IAddCertificationParams) {
// 调用钉钉通知函数
uniCloud.callFunction({
name: "dingtalk-robot",
data: { content: `有一个新的出题官认证申请,申请时间为${this.nowDate}\n申请内容为: ${JSON.stringify(params.content)}\n请及时查看,尤其是群主,你别忘记了!` },
data: {
content: `有一个新的出题官认证申请,申请时间为${
this.nowDate
}\n申请内容为: ${JSON.stringify(
params.content
)}\n请及时查看,尤其是群主,你别忘记了!`,
},
});
return await collection.add({
state: "pending",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace SearchService {
return await collection.add({
content: params.content,
[params.device_id ? 'device_id' : 'user_id']: params.device_id ? params.device_id : params.user_id,
create_date: this.nowDate
create_date: Date.now()
});
}
};
Expand Down
58 changes: 58 additions & 0 deletions uniCloud-aliyun/cloudfunctions/timing-satistics/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use strict';
const db = uniCloud.database();
const userCollection = db.collection("uni-id-users");
const questionCollection = db.collection("question");
const explanationCollection = db.collection("questionExplanation");
const areaCollection = db.collection("questionArea");
const hotCollection = db.collection("opendb-search-hot");
const certificationApplyOrderCollection = db.collection("certificationApplyOrder");
const $ = db.command.aggregate
exports.main = async (event, context) => {
// 用户表数量
const {
total: userTotal
} = await userCollection.count();
// 问题数量
const questionInfo = await questionCollection.aggregate().match({
state: "pass"
}).group({
_id: "$areaID",
num: $.sum(1)
}).end()
// 解答数量
const {
total: explanationTotal
} = await explanationCollection.count();
// 专区信息
const {
data: areaInfo
} = await areaCollection.get();
// 今日热搜词
const {
data: hotInfo
} = await hotCollection.field({
content: true
}).get();
// 出题官认证申请(只展示未处理)
const {
data: certificationInfo
} = await certificationApplyOrderCollection.where({
state: "pending"
}).skip(0).limit(10).orderBy("createTime", "desc").get();
// 构成统计数据
const mainStr = `今日用户数量: ${userTotal}
题目数据概览: ${questionInfo.data.map(q => {
return (areaInfo.find(a => a._id === q._id)).name + `(${q.num}道)`
})}
题解数量: ${explanationTotal}
今日热搜词: ${hotInfo.map(h => h.content).join(",")}
最近的认证申请(未处理): \n${certificationInfo.map(c => `-- 联系方式: ${c.content.contactDetails}, 擅长: ${c.content.filed}`).join("\n")}
`
// 发送钉钉通知
await uniCloud.callFunction({
name: "dingtalk-robot",
data: { content: `${mainStr}` }
})
//返回数据给客户端
return event
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// 本文件中的json内容将在云函数【运行】时作为参数传给云函数。
// 配置教程参考:https://uniapp.dcloud.net.cn/uniCloud/quickstart?id=runparam
{
}
8 changes: 3 additions & 5 deletions uniCloud-aliyun/cloudfunctions/uni-analyse-searchhot/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@ exports.main = async (event, context) => {
const SEARCHHOT_db = DB.collection(SEARCHHOT);
const SEARCHLOG_db = DB.collection(SEARCHLOG);
const timeEnd = Date.now() - SEARCHLOG_timeZone;

let {
data: searchHotData
data: searchLogData
} = await SEARCHLOG_db
.aggregate()
.match({
Expand All @@ -40,10 +39,9 @@ exports.main = async (event, context) => {
.end();

let now = Date.now();
searchHotData.map(item => {
searchLogData.map(item => {
item.create_date = now;
return item;
}).slice(0, SEARCHHOT_size);
// searchHotData = searchHotData.sort((a, b) => b.count - a.count).slice(0, SEARCHHOT_size);
return searchHotData.length ? await SEARCHHOT_db.add(searchHotData) : ''
return searchLogData.length ? await SEARCHHOT_db.add(searchLogData) : ''
};

0 comments on commit e1fc1bd

Please sign in to comment.