git仓库
gitee: malred/password-generator-wails-vue
gitee: malred/password-generator-wails-vue
github: https://github.com/malred/password-generator-wails-vue
wails是什么
我们用它来套壳前端项目(vue),打包成桌面端
思路
提供一个输入框(input),然后获取用户输入的字符串,通过select标签提供加密算法选项,点击生成按钮,根据选择的加密算法来给input里的字符串加密,然后在最底部显示加密结果
项目准备
wails安装
确保你的go版本在1.18及以上
`go install github.com/wailsapp/wails/v2/cmd/wails`@latest
创建项目
`wails init -n password-generator -t vue`
app.go
定义了结构体App,当编译的时候,wails会自动把App结构体上的方法转为js方法,可以供前端使用
比如这里的Greet方法
在frontend/wailsjs/go/main/App.js里可以看到对应的方法
vue部分
因为项目比较简单,我们的代码都写在app.vue
template 模板
一个input框,一个select选择,一个按钮
`<`template`>
<`div` `class`=`"container"`>
<`input`
`type`=`"text"`
`v-model`=`"inp"`
`placeholder`=`"Input your password to encrypt"`
/>
<`br` />
<`select` `name`=`"alg"` `id`=`"alg"` `v-model`=`"sel"`>
<`option` `:value`=`"v"` `v-for`=`"v in crypto"` `:key`=`"v"`>{``{ v }}</`option`>
</`select`>
<`br` />
<`button` `@click`=`"Gen"`>Generator!</`button`>
<`br` />
<`div`>{``{ genStr }}</`div`>
</`div`>
</`template`>`
script 脚本
`<script setup>
import crypto from `'./crypto'`
import { ref } from `'vue'`
`// App.go定义后被编译为js可以调用的方法`import { MD5, Sha1, HMAC_SHA256 } from `'../wailsjs/go/main/App'`
`// 选择框的值`const sel = ref(`'sha1'`)
`// 输入框的值`const inp = ref(`''`)
`// 加密后的字符串`let genStr = ref(`''`)
`// 点击按钮触发`const Gen = () => {
`// 如果inp框里没有输入值` if (!inp.value) {
return
}
`// 判断选择了什么加密方式并加密` `// console.log(sel.value)` if (sel.value === `'md5'`) {
MD5(inp.value).then(res => {
genStr.value = res
})
} else if (sel.value === `'sha1'`) {
Sha1(inp.value).then(res => {
genStr.value = res
})
} else if (sel.value === `'HMAC-SHA256'`) {
HMAC_SHA256(inp.value).then(res => {
genStr.value = res
})
}
`// 表单数据清空` inp.value = `''`
}
<`/script>`
`
crypto.js
返回一个数组,里面是加密方法的名称
` export default [
`"sha1"`,
`"md5"`,
`"HMAC-SHA256"`
]
`
style 风格
`<`style` `scoped`>
.`container` {
text-align: center;
margin-top: `16rem`;
}
`select` {
margin-top: `2rem`;
border: none;
outline: none;
width: `16rem`;
height: `3rem`;
background-color: `#faf1d8`;
font-size: `1.2rem`;
line-height: `1.2rem`;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
`/* padding-right: 2px; */`
text-align: center;
box-shadow: `2px` `2px` `2px` `1px` `rgba`(`0`, `0`, `0`, `0.2`);
border-radius: `0.5rem`;
}
`button` {
background-color: `#f2c64f`; `/* Green */`
border: none;
color: black;
border-radius: `0.5rem`;
padding: `3rem` `4rem`;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: `1.2rem`;
margin: `4px` `2px`;
cursor: pointer;
-webkit-transition-duration: `0.4s`; `/* Safari */`
transition-duration: `0.4s`;
}
`button`:hover {
box-shadow: `0` `12px` `16px` `0` `rgba`(`0`, `0`, `0`, `0.24`),
`0` `17px` `50px` `0` `rgba`(`0`, `0`, `0`, `0.19`);
}
`div` {
color: black;
font-weight: bold;
margin-top: `2rem`;
}
`button` {
margin-top: `2rem`;
position: relative;
background-color: `#4caf50`;
border: none;
font-size: `12`rempx;
color: `#ffffff`;
padding: `1rem`;
width: `200px`;
text-align: center;
-webkit-transition-duration: `0.4s`; `/* Safari */`
transition-duration: `0.4s`;
text-decoration: none;
overflow: hidden;
cursor: pointer;
}
`button`:after {
content: `''`;
background: `#90ee90`;
display: block;
position: absolute;
padding-top: `300%`;
padding-left: `350%`;
margin-left: `-20px` `!important`;
margin-top: `-120%`;
opacity: `0`;
transition: all `0.8s`;
}
`button`:active:after {
padding: `0`;
margin: `0`;
opacity: `1`;
transition: `0s`;
}
`input` {
outline: none;
`/* background-color: #4368d092; */`
`/* padding: 1rem .5rem; */`
border: `1px` solid `#fff`;
border-radius: `0.5rem`;
background-color: `#faf1d8`;
text-indent: `1rem`;
width: `16rem`;
height: `3rem`;
font-size: `1rem`;
font-weight: bold;
box-shadow: `2px` `2px` `2px` `1px` `rgba`(`0`, `0`, `0`, `0.2`);
}
`input`:placeholder-shown {
`/* border: 3px solid rgba(224, 224, 56, 0.762); */`
}
`input`::-webkit-input-placeholder {
`/* color: #2feb2f; */`
font-size: `1rem`;
font-weight: normal;
}
</`style`>`
assets/images/1.png 是从网上下载的图片,作为背景图
在style.css里修改背景图
html` {
`/* background-color: rgba(27, 38, 54, 1); */`
background: `url`(`'assets/images/1.png'`) no-repeat;
background-size: `100%` `100%`;
background-attachment: fixed;
text-align: center;
color: white;
}`
wails的App.go定义加密算法
`package main
import (
`"bytes"`
`"context"`
`"crypto/aes"`
`"crypto/cipher"`
`"crypto/hmac"`
`"crypto/md5"`
`"crypto/sha1"`
`"crypto/sha256"`
`"encoding/hex"`
`"fmt"`
)
`// App struct`type App struct {
ctx context.Context
}
`// NewApp creates a new App application struct`func `NewApp`() *App {
return &App{}
}
`// startup is called when the app starts. The context is saved// so we can call the runtime methods`func (a *App) `startup`(ctx context.Context) {
a.ctx = ctx
}
`// Greet returns a greeting for the given name`func (a *App) `Greet`(name `string`) `string` {
return fmt.`Sprintf`(`"Hello %s, It's show time!"`, name)
}
`// md5加密`func (a *App) `MD5`(str `string`) `string` {
h := md5.`New`()
h.`Write`([]`byte`(str))
return hex.`EncodeToString`(h.`Sum`(nil))
}
func (a *App) `HMAC_SHA256`(str `string`) `string` {
secret := `"mysecret"`
data := `"data"`
`// Create a new HMAC by defining the hash type and the key (as byte array)` h := hmac.`New`(sha256.New, []`byte`(secret))
`// Write Data to it` h.`Write`([]`byte`(data))
`// Get result and encode as hexadecimal string` sha := hex.`EncodeToString`(h.`Sum`(nil))
return sha
}
`// sha1加密`func (a *App) `Sha1`(data `string`) `string` {
sha1 := sha1.`New`()
sha1.`Write`([]`byte`(data))
return hex.`EncodeToString`(sha1.`Sum`([]`byte`(`""`)))
}
`
编译
如果要先运行看看结果
`wail dev`
打包
`wails build`
编译完成后,在根目录的build/bin下就是编译完成的exe