master
Evan Chen 2022-01-04 20:39:28 +08:00
parent 7a40fcbcc7
commit 90ecb636f0
11 changed files with 199 additions and 22 deletions

4
api.go
View File

@ -8,6 +8,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/line/line-bot-sdk-go/v7/linebot"
"github.com/rs/zerolog/log"
)
@ -26,6 +27,9 @@ func ApiUpdateEmail(c *gin.Context) {
}
DB.Model(&User{}).Where("id = ?", data.ID).Update("email", data.Email)
OK(c, "ok")
msg := linebot.NewTextMessage("更新成功!")
sticker := linebot.NewStickerMessage("1070", "17840")
SendMessage("", data.ID, msg, sticker, DefaultMsg())
}
func ApiPostReceipt(c *gin.Context) {

View File

@ -50,6 +50,8 @@ func postback(event *linebot.Event) {
ApiPrepareClaim(event)
case strings.HasPrefix(data, "cat="):
ApiListProductOfCat(event)
case strings.HasPrefix(data, "purchase="):
ApiPurchase(event)
case data == "list-tags":
ApiListCategories(event)
}
@ -62,6 +64,9 @@ func controller(event *linebot.Event) {
log.Error().Msg("controller not impemented")
return
}
if !valid(event) {
return
}
Hit(msg.Text, event.Source.UserID)
switch {
@ -80,6 +85,8 @@ func controller(event *linebot.Event) {
case strings.HasPrefix(msg.Text, "我是"):
case msg.Text == "我知道":
case msg.Text == "我要理賠":
case msg.Text == "修改完成":
case msg.Text == "我要投保":
default:
// route to watson

View File

@ -1,6 +1,7 @@
package main
import (
"strconv"
"strings"
"github.com/line/line-bot-sdk-go/v7/linebot"
@ -37,13 +38,40 @@ func ApiListProductOfCat(event *linebot.Event) {
data := event.Postback.Data
data = strings.TrimPrefix(data, "cat=")
msg := linebot.NewTextMessage(data + ":")
var prods []Product
DB.Find(prods, "id in (select product_id from product_categories where category_name = ?)", data)
columns := make([]*linebot.CarouselColumn, len(prods))
for i, prod := range prods {
columns[i] = linebot.NewCarouselColumn(
prod.Img, prod.Name, prod.Brief,
linebot.NewURIAction("保單詳細", flagBase+"/product/"+strconv.Itoa(int(prod.ID))),
linebot.NewPostbackAction("我要投保", "purchase="+prod.Name, "我要投保", ""),
)
}
template := linebot.NewCarouselTemplate(columns...)
msg := linebot.NewTemplateMessage("我要投保", template)
if _, err := SendMessage(event.ReplyToken, event.Source.UserID, msg); err != nil {
panic(err)
}
}
func ApiGetProduct(event *linebot.Event) {}
func ApiPurchase(event *linebot.Event) {
data := event.Postback.Data
data = strings.TrimPrefix(data, "purchase=")
prod := &Product{}
if err := DB.Preload("Categories").First(prod, "name = ?", data); err != nil {
panic(err)
}
// show amount and finish purchase
msg := linebot.NewTextMessage(`,
: XXX
`)
SendMessage(event.ReplyToken, event.Source.UserID, msg)
}
func ApiListRecommanded(event *linebot.Event) {
var prods []Product

View File

@ -1,9 +1,13 @@
package main
import "github.com/line/line-bot-sdk-go/v7/linebot"
import (
"strconv"
"github.com/line/line-bot-sdk-go/v7/linebot"
)
func ApiMe(event *linebot.Event) {
leftBtn := linebot.NewURIAction("修改資料", flagBase+"/profile")
leftBtn := linebot.NewURIAction("修改資料", flagBase+"/profile/"+event.Source.UserID)
rightBtn := linebot.NewMessageAction("我的保單", "我的保單")
template := linebot.NewConfirmTemplate("請問想辦理甚麼服務?", leftBtn, rightBtn)
msg := linebot.NewTemplateMessage("請問想辦理甚麼服務?", template)
@ -12,6 +16,28 @@ func ApiMe(event *linebot.Event) {
}
}
func valid(event *linebot.Event) bool {
msg, _ := event.Message.(*linebot.TextMessage)
if msg.Text == "我的資料" {
return true
}
usr := &User{}
if err := DB.First(usr, "id = ?", event.Source.UserID).Error; err != nil {
panic(err)
}
if usr.Email == "" {
text := "您的基本資料不完整, 請您協助填寫。"
tmp := linebot.NewButtonsTemplate("", "", text,
linebot.NewURIAction("點我填寫", flagBase+"/profile/"+event.Source.UserID))
msg := linebot.NewTemplateMessage(text, tmp)
if _, err := SendMessage(event.ReplyToken, event.Source.UserID, msg); err != nil {
panic(err)
}
return false
}
return true
}
func ApiMyOrders(event *linebot.Event) {
var orders []Order
DB.Order("product_id").Find(&orders, "user_id = ?", event.Source.UserID)
@ -36,7 +62,7 @@ func ApiMyOrders(event *linebot.Event) {
for i, prod := range products {
columns[i] = linebot.NewCarouselColumn(
prod.Img, prod.Name, prod.Brief,
linebot.NewURIAction("保單詳細", flagBase+"/product"),
linebot.NewURIAction("保單詳細", flagBase+"/product/"+strconv.Itoa(int(prod.ID))),
linebot.NewPostbackAction("我要理賠", "claim="+prod.Name, "我要理賠", ""),
// linebot.NewPostbackAction("我是"+prof.Name, "select="+prof.Name, "我是"+prof.Name, ""),
)

2
db.go
View File

@ -44,7 +44,7 @@ func migrateDB() {
if err := DB.SetupJoinTable(&User{}, "Products", &Order{}); err != nil {
panic(err)
}
if err := DB.AutoMigrate(&Node{}, &User{}, &Profile{}, &Product{}, &Order{}); err != nil {
if err := DB.AutoMigrate(&Node{}, &User{}, &Profile{}, &Product{}, &Order{}, &Price{}); err != nil {
panic(err)
}
}

View File

@ -77,13 +77,16 @@ func main() {
server.GET("/check", func(c *gin.Context) {
c.Writer.Write(check_web)
})
server.GET("/profile", func(c *gin.Context) {
server.GET("/profile/:uid", func(c *gin.Context) {
log.Debug().Str("uid", c.Param("uid")).Msg("profile")
c.Writer.Write(profile_web)
})
server.GET("/claim", func(c *gin.Context) {
server.GET("/claim/:oid", func(c *gin.Context) {
log.Debug().Str("oid", c.Param("oid")).Msg("claim")
c.Writer.Write(claim_web)
})
server.GET("/product", func(c *gin.Context) {
server.GET("/product/:pid", func(c *gin.Context) {
log.Debug().Str("pid", c.Param("pid")).Msg("product")
c.Writer.Write(product_web)
})

View File

@ -27,14 +27,29 @@ type User struct {
type Profile struct {
ID uint `gorm:"primaryKey"`
Name string
Brief string
Img string
Name string
Brief string
Img string
Age int
Gender string
Occupation string
PersonalID string
Phone string
Address string
CreatedAt time.Time
UpdatedAt time.Time
}
type Price struct {
ProfileID uint `gorm:"primaryKey"`
ProductID uint `gorm:"primaryKey"`
PlanPrice float32
PlanUnit int
Detials string
}
type Product struct {
ID uint `gorm:"primaryKey"`

View File

@ -1,11 +1,25 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>核身</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
<title>核身</title>
</head>
<body>
<h1>HI</h1>
<section class="hero is-fullheight" style="background-color:#d70c18;">
<div class="hero-body">
<div class="container">
<h1 class="has-text-white has-text-weight-bold has-text-centered is-size-2">身分檢核中</h1>
<br>
<progress class="progress is-large is-info" max="100">60%</progress>
</div>
</div>
</section>
</body>
<script>
// setTimeout(function(){
// window.location = "https://line.me/R/oaMessage/@565zednv/?完成"
// },1000)
</script>
</html>

View File

@ -3,6 +3,7 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
<title>上傳收據</title>
</head>
<body>

View File

@ -3,6 +3,7 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
<title>保單詳細</title>
</head>
<body>

View File

@ -1,11 +1,89 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>修改基本資料</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>修改基本資料</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
</head>
<body>
<h1>基本資料</h1>
<section class="hero is-fullheight" style="background-color:#d70c18;" id="loader">
<div class="hero-body">
<div class="container">
<h1 class="has-text-white has-text-weight-bold has-text-centered is-size-2">身分檢核中</h1>
<br>
<progress class="progress is-large is-info" max="100">60%</progress>
</div>
</div>
</section>
<div id="err" class="notification is-danger is-light is-hidden"
style="position: absolute;width: 100%;">
<button class="delete" onclick="close()"></button>
電子郵件地址格式錯誤
</div>
<section class="hero is-danger is-fullheight is-hidden"
style="background-color:#d70c18;" id="form">
<div class="hero-body">
<div class="container">
<div class="field">
<label class="label has-text-white">Email</label>
<div class="control">
<input id="email" class="input is-danger" type="email" placeholder="請輸入電子郵件">
</div>
</div>
<div class="buttons is-right">
<button id="save" class="button" onclick="save()">送出</button>
</div>
</div>
</div>
</section>
</body>
<script>
setTimeout(function(){
let loader = document.getElementById('loader');
loader.classList.add("is-hidden")
let form = document.getElementById('form');
form.classList.remove("is-hidden")
},3000)
function save(){
let btn = document.getElementById('save');
btn.classList.add("is-loading")
let el = document.getElementById('email');
// get uid
let parts = window.location.href.split('/');
let uid = parts.pop() || parts.pop();
fetch("/api/email", {
method: 'POST',
body: JSON.stringify({id: uid,email: el.value}),
headers: new Headers({
'Content-Type': 'application/json'
})
})
.then(function(res){
if (res.status != 200){
let err = document.getElementById('err');
err.classList.remove("is-hidden")
} else {
setTimeout(function(){
window.location = "https://line.me/R/oaMessage/@565zednv/?"
},500)
}
})
.catch(function(){})
.finally(function() {
btn.classList.remove("is-loading")
})
}
function close(){
let err = document.getElementById('err');
err.classList.add("is-hidden")
}
</script>
</html>