⚠️ FBI Warning:本文纯属作者自娱自乐,数字人的观点不代表 CEO 本人的观点,请大家不要上当受骗!!
哪个公司的 CEO 不想拥有一个自己的数字克隆?
想象?一下,如果 CEO 数字克隆上线了,那他是不是就可以一天约见 100 个投资人了?把他接入企业官方公众号后台作为客服,24 小时不吃饭不睡觉不喝水给用户答疑解惑,想想就很刺激!感觉 CEO 在给我打工✅
环界云的 CEO 做到了!先来看看效果:
怎么样,你也想拥有一个自己的数字克隆么?问题不大,跟着我操作。
首先你需要准备自己的语料,我们 CEO 的语料就是来自各种同性交友大会的演讲内容,如果你的语料不够多,那就得自己想办法了。
当然,本文提供的方法不仅仅适用于数字克隆,你可以基于任意专有知识库来打造一个私有领域的专家或者客服,然后再对接到公众号,它不香吗?
首先你需要有一个微信公众号,而且是已经认证的公众号,因为公众号强制要求服务器每次必须在 15s 以内回复消息,公众号平台在发送请求到服务器后,如果 5s 内没收到回复,会再次发送请求等候 5 秒,如果还是没有收到请求,最后还会发送一次请求,所以服务器必须在 15s 以内完成消息的处理。如果超过 15s 还没有返回怎么办?那就超时了,用户将永远都收不到这条消息。
如果你想突破 15s 限制怎么办?
本文给出的方法是基于微信客服消息进行回复,所以需要一个已认证的公众号。如果是未认证的公众号,就需要你自己研究流式响应了,本文不做赘述。
其次你需要注册一个 FastGPT 账号。它是一个 ChatGPT 平台项目,目前已经集成了 ChatGPT、GPT4 和 Claude,可以使用任意文本来训练自己的知识库。
? 注册链接:http://fastgpt.run/?inviterId=64215e9914d068bf840141d0
注册完 FastGPT 后,你可以直接填写自己的 API Key 进行使用,也可以在 FastGPT 平台充值使用。
接下来点击侧栏的数据库图标进入知识库界面,然后点击 “+” 号新建一个知识库。
点击「导入」,可以看到有 3 种方法来导入知识库。
如果你有多个文本文件,可以直接选择「文本/文件拆分」进行导入,模式建议选「QA 拆分」,也可以直接分段。
导入之后,就会开始训练,训练完成后的效果:
最后你还需要一个平台来开发你的应用,那当然是 Laf 啦。据环界云 CEO 数字克隆所说?,Laf 是一个 Serverless 框架,可以用来快速开发具有 AI 能力的分布式应用,助你像写博客一样写代码,随时随地快速发布上线应用。真⭕五分钟上线 CEO 数字克隆!
? Laf 注册链接:http://laf.run
一切工作准备就绪后,开始动笔写亿点点代码。
先新建应用,直接新建免费的进行测试:
点击「+」新建云函数:
然后将下面的云函数代码直接复制粘贴到 Web IDE 中:
import cloud from '@lafjs/cloud';
import * as crypto from 'crypto';
// 公众号配置
const appid = 'wxb1833715d8f0809d'
const appsecret = 'fd76ce714a8083112100c2160b2f2c5d'
const wxToken = 'test';
// fastgpt配置
const apikey = "63f9a14228d2a688d8dc9e1b-xsyvfby3cui09tfcvxen3"
const modelId = "642adec15f01d67d4613efdb"
// 创建数据库连接并获取Message集合
const db = cloud.database();
const _ = db.command
const Message = db.collection('messages')
// 处理接收到的微信公众号消息
export async function main(event) {
// const res = await cloud.fetch.post(` http://api.weixin.qq.com/cgi-bin/menu/create?access_token=${await getAccess_token()}`, {
// button: [
// {
// "type": "click",
// "name": "清空记录",
// "key": "CLEAR"
// },
// ]
// })
const { signature, timestamp, nonce, echostr } = event.query;
// 验证消息是否合法,若不合法则返回错误信息
if (!verifySignature(signature, timestamp, nonce, wxToken)) {
return 'Invalid signature';
}
// 如果是首次验证,则返回 echostr 给微信服务器
if (echostr) {
return echostr;
}
// -------------- 正文开始
const payload = event.body.xml;
const sessionId = payload.fromusername[0]
console.log(payload)
// 点击了清空记录
if (payload.msgtype[0] === 'event' && payload.eventkey[0] === 'CLEAR') {
console.log(1111)
await Message.where({ sessionId: sessionId }).remove({ multi: true })
await replyBykefu('记录已清空', sessionId)
return 'clear record'
}
// 仅做文本消息例子
if (payload.msgtype[0] !== 'text') return 'no text'
const newMessage = {
msgid: payload.msgid[0],
question: payload.content[0].trim(),
username: payload.fromusername[0],
sessionId,
createdAt: Date.now()
}
await replyText(newMessage, payload.fromusername[0])
return 'success'
}
// 处理文本回复消息
async function replyText(message, touser) {
const { question, sessionId, msgid } = message;
// 重复的内容,不回复
const { data: msg } = await Message.where({ msgid: message.msgid }).getOne()
if (msg) return
console.log("收到用户消息", touser, message)
// 立即添加一条待回复记录
await Message.add(message);
// 回复提示
await replyBykefu("?机器人正在思考?中...", sessionId)
await changesState(sessionId)
const reply = await getFastGptReply(question, sessionId);
const { answer } = reply;
await Message.where({ msgid: message.msgid }).update({
answer,
});
// return answer;
await replyBykefu(answer, touser)
}
// 获取微信公众号ACCESS_TOKEN
async function getAccess_token() {
const shared_access_token = await cloud.shared.get("mp_access_token")
if (shared_access_token && shared_access_token.access_token && shared_access_token.exp > Date.now()) {
return shared_access_token.access_token
}
// ACCESS_TOKEN不存在或者已过期
// 获取微信公众号ACCESS_TOKEN
const mp_access_token = await cloud.fetch.get(`http://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${appsecret}`)
mp_access_token.data.access_token && cloud.shared.set("mp_access_token", {
access_token: mp_access_token.data.access_token,
exp: Date.now() + 7100 * 1000
})
return mp_access_token.data.access_token
}
// 公众号客服回复文本消息
export async function replyBykefu(message, touser) {
// 判断是否为中文字符
function isChinese(char) {
return /[\u4e00-\u9fa5]/.test(char) // 判断是否是中文字符
}
// 拆分文本长度
function splitText(text) {
let result = []
let len = text.length
let index = 0
while (index < len) {
let part = ''
let charCount = 0
while (charCount < 800 && index < len) {
let char = text[index]
charCount++
part += char
if (isChinese(char)) charCount++ // 中文字符计数+1
index++
}
result.push(part)
}
return result
}
// 定义休眠函数
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) };
const access_token = await getAccess_token()
let text = splitText(message)
let len = splitText(message).length
try {
for (let i = 0; i < len; i++) {
let part = text[i] // 获取第 i 段
await sleep(1000)
// 回复消息
const res = await cloud.fetch.post(`http://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${access_token}`, {
"touser": touser,
"msgtype": "text",
"text":
{
"content": part
}
})
}
} catch (err) {
console.log(err)
}
}
// 修改公众号回复状态
export async function changesState(touser) {
const access_token = await getAccess_token()
// 修改正在输入的状态
const res = await cloud.fetch.post(`http://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=${access_token}`, {
"touser": touser,
"command": "Typing"
})
}
// 校验微信服务器发送的消息是否合法
export function verifySignature(signature, timestamp, nonce, token) {
const arr = [token, timestamp, nonce].sort();
const str = arr.join('');
const sha1 = crypto.createHash('sha1');
sha1.update(str);
return sha1.digest('hex') === signature;
}
// 返回组装 xml
export function toXML(payload, content) {
const timestamp = Date.now();
const { tousername: fromUserName, fromusername: toUserName } = payload;
return `
<xml>
<ToUserName><![CDATA[${toUserName}]]></ToUserName>
<FromUserName><![CDATA[${fromUserName}]]></FromUserName>
<CreateTime>${timestamp}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${content}]]></Content>
</xml>
`
}
// 调用 fastgpt 回答
async function getFastGptReply(question, sessionId) {
const res = await db.collection('messages')
.where({ sessionId })
.get()
// 获取最多10组上下文
const list = res.data.slice(-10)
const prompts = list.map((item) => [{
obj: "Human",
value: item.question || ''
}, {
obj: "AI",
value: item.answer || ''
}]).concat({
obj: "Human",
value: question
}).flat()
const config = {
method: 'post', // 设置请求方法为POST
url: 'http://fastgpt.run/api/openapi/chat/chat', // 设置请求地址
headers: { // 设置请求头信息
apikey,
'Content-Type': 'application/json'
},
data: { // 设置请求体数据
modelId,
isStream: false,
prompts
}
}
try {
const ret = await cloud.fetch(config)
console.log("fastgpt响应", ret.data)
return { answer: ret.data.data || ret.data || '' }
} catch (e) {
console.log("出错了", e.response)
return {
error: "问题太难了 出错了. (uДu〃).",
}
}
}
整个云函数的调用流程如下:
❶ 当收到微信公众号消息时,首先调用 main 函数。在 main 函数中,首先验证消息是否合法,如果不合法则返回错误信息。如果是首次验证,则返回 echostr 给微信服务器。
❷ 接着根据消息类型进行处理。对于文本消息,调用 replyText 函数进行处理。
❸ 在 replyText 函数中,首先检查是否为重复的内容,如果是则不回复。然后将用户发送的问题存入数据库,并回复提示信息给用户,表示机器人正在思考中。
❹ 接下来调用 getFastGptReply 函数获取 FastGPT 的回答。在 getFastGptReply 函数中,首先从数据库中获取最多 10 组上下文信息,然后将问题和上下文信息一起发送给 FastGPT。接收到 FastGPT 的回答后返回给 replyText 函数。
❺ 回到 replyText 函数,将 FastGPT 返回的回答更新到数据库中,并通过客服接口将回答发送给用户。在发送回答之前,会调用 changesState 函数修改公众号回复状态为正在输入中。
❻ 调用 replyBykefu 函数通过微信公众号客服接口发送文本消息给用户。在 replyBykefu 函数中,首先根据文本长度拆分成多段,并逐段发送给用户。
先不要改动代码中的任何内容,后面会告诉你如何修改。
点击「发布」:
最后复制已发布的函数地址:
这一步我们需要在微信公众号平台上配置开发者信息,并将服务器地址设置为部署好的云函数服务地址。步骤如下:
首先登录微信公众平台,点开左侧的「设置与开发」,点击「基本设置」,然后点击「服务器配置」,服务器配置那里点击修改配置:
将之前的云函数服务地址复制到「服务器 URL」中,下边的 Token 与云函数代码中的 token 保持一致,下边的 EncodingAESKey 点击右侧随机生成就行,然后点击提交:
返回 token 校验成功即可。
获取公众号的 AppID 和 AppSecret:
这一步的操作请务必不要忘记!!!你需要把 laf.run 的 IP 地址全部添加到 IP 白名单中:
laf.run 域名的 IP 地址可通过以下命令获取:
$ dig +short laf.run
112.124.8.17
120.26.163.28
112.124.9.83
47.97.22.68
112.124.9.194
114.55.179.67
114.55.177.246
120.27.246.172
120.26.161.248
47.97.5.237
把获取到的 AppID 和 AppSecret 填写到 Laf 云函数中,然后点击「发布」:
最后在公众号平台点击「启用」即可。
接下来开始配置 FastGPT,首先新建一个 API Key:
然后新建一个应用:
然后选择需要关联的知识库:
可以根据自己的需求设置一下温度、搜索模式和系统提示词,最终点击「保存修改」。
获取应用的 modelId:
将你获取的 API Key 和 modelId 填写到 Laf 云函数中,修改完成后点击发布:
到公众号里测试一下:
完美?
当然,接入数字 CEO 只是图个乐呵,演示完了就撤了。目前 Laf 公众号真正接入的是 Laf 专有模型,可以回答与 Laf 相关的任何问题,感兴趣的小伙伴可以去体验一下,公众号的名字是:Laf 开发者。
如果发送消息后无响应,可以先去 Laf 控制台的日志中检查是否收到用户消息,有下面的提示代表是正常的(可能需要点下搜索才能刷新出来)。
如果收到了消息,但是没有回复,八成是公众号没有发送客服消息权限。对应是下图的权限:
px像素实际上是一个颜色点,所以又称像素点。大量不同颜色点组成一张图像,因此图像的基本单位是像素px(没有比像素更精细的单位了)。 像素主要用来表示图像大小和显示器分辨率(如1920*1080px)。像素本身的物理尺寸不固定,所以它的物理尺寸没有意义,有意义的是它的数量。为什么像素的物理尺寸不固定?像素本身不是物理世界的单位,是一个相对单位,尺寸可大可小。在高密度的屏幕上像素会变小,显示效果更清晰。因为“像素量px=像素密度ppi x屏幕尺寸in”,同样是1英寸的屏幕,密度越大,像素越多,则单个像素的物理尺寸越小。都是图片相关信息,图片体积和像素有什么关系?通常所说的100KB的图片指的就是图片的体积,首先一张图像在存储时,会描述每个像素点的颜色信息、位置、数量,这些描述数据就是图像的体积,如果像素越多自然图像体积越大。假如一张图片都是一个颜色,图像在保存时就会压缩,只存一个像素点的颜色信息,这样的图像体积会小很多。所以,像素点越多,颜色越复杂,图像体积越大。为什么我们要买高像素的相机?日常我们所说的几百万像素的相机,这个几百万像素指的是拍摄最大像素量照片时,图像宽高位置上像素量的乘积
前言ECharts是一个使用JavaScript实现的开源可视化库,涵盖各行业图表,满足各种需求。ECharts下载与使用可以在直接下载echarts.min.js并用<script>标签引入。下载地址https://cdn.staticfile.org/echarts/4.7.0/echarts.min.js 开发环境下可以使用源代码版本echarts.js并用<script>标签引入,源码版本包含了常见的错误提示和警告。下载地址https://cdn.staticfile.org/echarts/4.7.0/echarts.js使用在线CDN方法: StaticfileCDN(国内):https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js cdnjs:https://cdnjs.cloudflare.com/ajax/libs/echarts/4.3.0/echarts.min.js生成环形饼图首先定义options作为环状图的参数,options.series:系列数据列表列表。每个系列通过type决
OpenGLES(三)-GLKit:多边形纹理、旋转本文中会省略关于GLKit最基本的API的注释,如果需要详细注释可以看另一篇OpenGLES(二)-纹理贴图展示效果在本案例中增加了固定光源,让物体更加逼真。1.上下文创建不同于上文中的GLKView的创建方式。使用这种initWithFrame方式可以不用依赖GLKViewController。content=[[EAGLContextalloc]initWithAPI:kEAGLRenderingAPIOpenGLES3]; if(!content){return;} [EAGLContextsetCurrentContext:content]; //GLKView创建 glkView=[[GLKViewalloc]initWithFrame:CGRectMake(0,100,UIScreen.mainScreen.bounds.size.width,UIScreen.mainScreen.bounds.size.height)context:content]; //必须注册代理 glkView.delegate=self; s
Vite2自2月17号份发布之后,收获了前端圈的一片哀嚎:学不动了……不不不,你得学!Vite(法语意思是“快”,发音为/vit/,类似veet)是一种全新的前端构建工具。你可以把它理解为一个开箱即用的开发服务器+打包工具的组合,但是更轻更快。Vite利用浏览器原生的ES模块支持和用编译到原生的语言开发的工具(如esbuild)来提供一个快速且现代的开发体验。官网: https://cn.vitejs.dev/ github: https://github.com/vitejs/docs-cn图片.png优点;?极速的服务启动使用原生ESM文件,无需打包! ⚡️轻量快速的热重载无论应用程序大小如何,都始终极快的模块热重载(HMR) ?️丰富的功能对TypeScript、JSX、CSS等支持开箱即用。 ?优化的构建可选“多页应用”或“库”模式的预配置Rollup构建 ?通用的插件在开发和构建之间共享Rollup-superset插件接口。 ?完全类型化的API灵活的API和完整TypeScript类型搭建第一个Vite项目兼容性注意Vite需要Node.js版本>=12.0.0。使
前面我们已经完整的介绍了performance_schema、sys、information_schema三个系统库,今天开始我们为大家开启"全方位认识mysql系统库"系列,这也是MySQL中的最后一个系统库,在更早之前,我们在《MySQL的help命令你真的会用吗?》一文中其实已经介绍过mysql系统库的帮助信息表了。在接下来的系列文章中,我们将全面介绍mysql系统库。下面,请跟随我们一起开始mysql系统库的学习之旅吧。MySQL访问权限系统表包含如下几张表:user:包含用户帐户和全局权限和其他非权限列表(安全配置选项和资源控制选项列)db:数据库级别的权限表tables_priv:表级别的权限表columns_priv:列级权限表procs_priv:存储过程和函数权限表proxies_priv:代理用户权限表PS:要更改权限表的内容,推荐使用帐号管理语句(如:CREATEUSER、GRANT、REVOKE等)来间接修改,不建议直接使用DML语句修改权限表,否则后果自负以下内容主要针对MySQL5.7版本进行整理1、user该表提供查询全局权限信息,该表
选自arXiv作者:AlexiaJolicoeur-Martineau编辑:小舟、蛋酱SVM是机器学习领域的经典算法之一。如果将SVM推广到神经网络,会发生什么呢?支持向量机(SupportVectorMachine,SVM)是大多数AI从业者比较熟悉的概念。它是一种在分类与回归分析中分析数据的监督式学习模型与相关的学习算法。给定一组训练实例,每个训练实例被标记为属于两个类别中的一个或另一个,SVM训练算法创建一个将新的实例分配给两个类别之一的模型,使其成为非概率二元线性分类器。SVM模型将实例表示为空间中的点,这样映射就使得单独类别的实例被尽可能宽的明显的间隔分开。然后,将新的实例映射到同一空间,并基于它们落在间隔的哪一侧来预测所属类别。除了进行线性分类之外,SVM还可以使用所谓的核技巧有效地进行非线性分类,将其输入隐式映射到高维特征空间中。本文将介绍一篇来自蒙特利尔大学的论文《SVM、Wasserstein距离、梯度惩罚GAN之间的联系》。在这篇论文中,研究者阐述了如何从同一框架中得到SVM和梯度惩罚GAN。据论文一作介绍,这项研究的灵感来自她的博士资格考试。在准备过程中,她学习了
Python时间处理# _*_ coding: utf-8 _*_ import time import calendar import datetime # time模块中的三种时间形式 print("time stamp:", time.time()) # 时间戳 print("local time:", time.localtime()) # struct_time类型的本地时间 print("utc time:", time.gmtime()) # struct_time类型的utc时间 # time模块中,三种时间形式之间的转换 time_stamp = time.time() # 时间戳 local_time = time.localtime(time_stamp) # 时间戳转struct_time类型的本地时间 utc_time = time.gmtime(time_s
创建运行AR会话的应用程序,并使用平面检测使用SceneKit放置3D内容。下载软件开发工具包iOS11.3+Xcode10.0+Beta概观此示例应用程序运行ARKit世界跟踪会话,其内容显示在SceneKit视图中。为了演示平面检测,应用程序只需放置一个SCNPlane对象来可视化每个检测到ARPlaneAnchor对象。配置并运行AR会话ARSCNView类是包括一个SceneKit视图ARSession管理创建的增强现实(AR)的经验所需要的运动跟踪和图像处理对象。但是,要运行会话,您必须提供会话配置。架构图:ARKit视图拥有ARSession,需要ARConfiguration才能运行。ARWorldTrackingConfiguration提供高精度的运动跟踪,并支持您将虚拟内容与真实世界的表面相关联的功能。要启动AR会话,请使用所需的选项(例如平面检测)创建会话配置对象,然后在ARSCNView实例的session对象上调用该方法:run(_:options:)letconfiguration=ARWorldTrackingConfiguration() configu
注意:本文分享给安全从业人员、网站开发人员以及运维人员在日常工作防范恶意攻击,请勿恶意使用下面介绍技术进行非法攻击操作。。[TOC]0x00前言介绍描述:HPP参数污染的定义:HTTPParameterPollution简称HPP也称之为“HPP参数污染”,HPP是一种注入型的漏洞攻击者通过在HTTP请求中插入特定的参数来发起攻击,如果Web应用中存在这样的漏洞,可以被攻击者利用来进行客户端或者服务器端的攻击还能绕过WAF。0x01HPP原理描述:简单的说就是使用相同的名称提供多个HTTP参数可能会导致应用程序以意想不到的方式解释值。 由于HTTP参数污染(简言之HPP)影响所有web技术的构建块,所以存在服务器端和客户端攻击;通过利用这些效果攻击者可以绕过输入验证、触发应用程序错误或修改内部变量值。 通过上面OWASP的截取WIKI我们知道实际这个漏洞就是采用多个同名参数,比如: #E.G: https://weiyigeek.com/test.php?color=red&color=blue复制不同的后端对其解析是不同的备忘清单如下:WeiyiGeek.补充:Web服务器参
功能描述CreateMediaJobs接口用来提交一个任务。 请求请求示例POST/jobsHTTP/1.1 Host:<BucketName-APPID>.ci.<Region>.myqcloud.com Date:<GMTDate> Authorization:<AuthString> Content-Length:<length> Content-Type:application/xml <body>复制 说明: Authorization:AuthString(详情请参见请求签名文档)。 请求头此接口仅使用公共请求头部,详情请参见公共请求头部文档。 请求体该请求操作的实现需要有如下请求体。 <Request> <Tag>SuperResolution</Tag> <Input> <Object></Object> </Input> <Operation> <TemplateId>t14
1.接口描述接口请求域名:iotvideoindustry.tencentcloudapi.com。 获取预置位列表 默认接口请求频率限制:20次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:DescribePresetList。 Version 是 String 公共参数,本接口取值:2020-12-01。 Region 是 String 公共参数,详见产品支持的地域列表。 ChannelId 是 String 视频通道唯一标识 DeviceId 是 String 设备唯一标识 3.输出参数 参数名称 类型 描述 Data ArrayofPresetItem 预置列表注意:此字段可能返回null,表示取不到有效值。 RequestI
作者:霜序 校稿:袋鼠云数栈前端团队运营小组 该文章包含如下内容 受控与非受控组件 非受控组件 受控组件 受控和非受控组件边界 反模式 解决方案 前言 在HTML中,表单元素(<input>/<textarea>/<select>),通常自己会维护state,并根据用户的输入进行更新 <form> <label> 名字: <inputtype="text"name="name"/> </label> <inputtype="submit"value="提交"/> </form> 复制 在这个HTML中,我们可以在input中随意的输入值,如果我们需要获取到当前input所输入的内容,应该怎么做呢? 受控与非受控组件 非受控组件(uncontrolledcomponent) 使用非受控组件,不是为每个状态更新编写数据处理函数,而是将表单数据交给DOM节点来处理,可以使用Ref来获取数据 在非受控组件中,希望能够赋予表单一个初始值,但是不去控制后续的更新。可以采用d
我在撰写《Vue2实践揭秘》时采用的vue-cli版本是v2.5.1,由于实体书的出版周期比电子书的要长,所以到全书出版vue-cli已经更新到v2.8.2了,我在书中曾经对vue-cli的全部官方模板进行过一个全面的解释,今天看了到这个更新版本算一算日子也已经与我写书时相距接近半年了,所以也特意重新来对每个模板过了一遍,作为对《Vue2实践揭秘》的补充更新吧。 先来看看有啥不同: 由于Webpack进行了一次很大的升级,所以可能在2.8之前的一些vue项目会导致不能运行,这是由于webpack这次的升级实在太过于恶心,竟然直接修改配置项的名称,最不可以理喻的是为强制loader引用要加入loader的名称后缀,实在是影响生产力的一次升级。 官方Webpack模板的内容也没啥新的变化,具体的内容我在《Vue2实践揭秘》中已经列出。新版本的可能只是存一些小小的细微不同,这并不会很重要,因为总体的思路并没有什么本质上的变化,新的变更使用新版本的方式就好了。 在vue-cliv2.8.2中多了一个叫PWA的全新模板。按照这里的解释这是一个基于vue-cli的webpack模板,(渐进式网页
判断线程池中所有线程是否执行完毕 1.根据线程池中的总线程数目等于完成的线程数目 packagecom.luna.thread; importjava.util.Random; importjava.util.concurrent.LinkedBlockingQueue; importjava.util.concurrent.ThreadPoolExecutor; importjava.util.concurrent.TimeUnit; publicclassThreadsIsDone{ publicstaticvoidmain(String[]args){ //创建一个10个线程的线程池 ThreadPoolExecutorpool=newThreadPoolExecutor(10,10,0L, TimeUnit.MILLISECONDS, newLinkedBlockingQueue<Runnable>()); for(inti=0;i<10;i++){ pool.submit(newRunnable(){ publicvoidrun(){ S
由于页面长时间未操作,出现登录超时,用户再次刷新页面,系统会自动跳转到登录页面。当用户重新登录后,怎么才能跳转到原来的页面呢?解决的方法如下: /** *获取request请求中的参数 *@paramsb *@paramreq *@return */ @SuppressWarnings("all") privateStringBuffergetRequestParameters(StringBuffersb,HttpServletRequestreq){ Mapmap=req.getParameterMap(); Stringstr="?"; if(!map.isEmpty()){ for(Objectkey:map.keySet()){ String[]values=(String[])map.get(key); for(Stringvalue:values){ str+=key+"="+value+"&"; } } str=str.substring(0,str.length()-1); } returnsb.append(str); }复制 /** *在调用Cont
微信小程序之蓝牙BLE踩坑记录 前言 前段时间接手了一个微信小程序的开发,主要使用了小程序在今年3月开放的蓝牙API,此过程踩坑无数,特此记录一下跳坑过程。顺便开了另一个相关的小项目,欢迎start和fork: BLE_MiniProgram API简介 微信小程序目前有蓝牙API共18个,其中操作蓝牙适配器的共有4个,分别是 wx.openBluetoothAdapter初始化蓝牙适配器 wx.closeBluetoothAdapter关闭蓝牙模块 wx.getBluetoothAdapterState获取本机蓝牙适配器状态 wx.onBluetoothAdapterStateChange监听蓝牙适配器状态变化事件复制 连接前使用的共有4个,分别是 wx.startBluetoothDevicesDiscovery开始搜寻附近的蓝牙外围设备 wx.stopBluetoothDevicesDiscovery停止搜寻附近的蓝牙外围设备 wx.getBluetoothDevices获取所有已发现的蓝牙设备 wx.onBluetoothDeviceFound监听寻
SELECTTOP30[TotalCost]=ROUND(avg_total_user_cost*avg_user_impact*(user_seeks+user_scans),0),avg_user_impact,TableName=statement,[EqualityUsage]=equality_columns,[InequalityUsage]=inequality_columns,[IncludeCloumns]=included_columnsFROMsys.dm_db_missing_index_groupsgINNERJOINsys.dm_db_missing_index_group_statssONs.group_handle=g.index_group_handleINNERJOINsys.dm_db_missing_index_detailsdONd.index_handle=g.index_handlewherestatementlike'%ecology%'ORDERBY[TotalCost]DESC;CREATEINDEXIDX_WFTORONworkfl
Android经典的开源项目其实非常多,但是国内的博客总是拿着N年前的一篇复制来复制去,实在是不利于新手学习。今天爬爬把自己熟悉的一些开源项目整理起来,希望能对Android开发同学们有所帮助。另外,如果你有比较好的项目推荐,也烦请在评论里分享出来,我会定期更新博客内容。 项目篇: Apollo音乐播放器:就一个播放器,但是实现的很好 oschina客户端:oschina网站的客户端哦,wp版,iOS版都有开源 xabber实时聊天工具(基于xmpp协议):不评价了,反正算是同类中比较好的了 四次元新浪微博客户端:今天才知道是开源的,赶紧收藏 Google IO:谷歌开发者大会应用,虽然有点难懂,还是很有参考价值(比如其中的图片加载) eoe客户端:eoe网站Android客户端也开源咯,嘿嘿 photup:一个上传图片到facebook的客户端,其中使用了很多开源项目,作者(chrisbanes)本身也非常NB~ dribbo:碎星(Fuubo的作者)写的一个dribbble的客户端 dashclock:4.2以上的锁屏插件,这应该是目前做的最好的锁屏插件了吧,居然是开源
目录: 通用操作 条件函数 前提: importarcpy fromarcpy.saimport* 1、通用操作 设置工作路径:arcpy.env.workspace("path_of_environment") 并行处理: arcpy.env.parallelProcessingFactor="n%" # 使用指定百分比计算进程数量:进程数量=系统核数量*n/100 arcpy.env.parallelProcessingFactor = "n" # 使用指定的进程数量 读取tif为栅格数据:arcpy.Raster(''path/to/tif_file") 保存生成的栅格数据:ras.save("path/to/save") 获取栅格范围:inRas.extent.XMin,inRas.extent.YMin,inRas.extent.XMax,inRas.extent.YMax 栅格行列数(ncols,xrows):ras.