Switch webui card import to textarea input
Signed-off-by: Sean Du <do4suki@gmail.com>
This commit is contained in:
@@ -1,16 +1,12 @@
|
|||||||
package webui
|
package webui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
|
||||||
"honoka-chan/internal/middleware"
|
"honoka-chan/internal/middleware"
|
||||||
unitmodel "honoka-chan/internal/model/unit"
|
unitmodel "honoka-chan/internal/model/unit"
|
||||||
usermodel "honoka-chan/internal/model/user"
|
usermodel "honoka-chan/internal/model/user"
|
||||||
"honoka-chan/internal/router"
|
"honoka-chan/internal/router"
|
||||||
"honoka-chan/internal/utils"
|
|
||||||
"honoka-chan/pkg/db"
|
"honoka-chan/pkg/db"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -24,52 +20,57 @@ type ErrMsg struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func upload(ctx *gin.Context) {
|
func upload(ctx *gin.Context) {
|
||||||
file, err := ctx.FormFile("file")
|
content := strings.TrimSpace(ctx.PostForm("content"))
|
||||||
utils.CheckErr(err)
|
if content == "" {
|
||||||
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "请输入导入内容!"})
|
||||||
tmpPath := path.Join("./temp", file.Filename)
|
return
|
||||||
err = ctx.SaveUploadedFile(file, tmpPath)
|
}
|
||||||
utils.CheckErr(err)
|
|
||||||
|
|
||||||
session := db.UserEng.NewSession()
|
session := db.UserEng.NewSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
if err = session.Begin(); err != nil {
|
if err := session.Begin(); err != nil {
|
||||||
session.Rollback()
|
session.Rollback()
|
||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: err.Error()})
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.Open(tmpPath)
|
lines := strings.Split(content, "\n")
|
||||||
if err != nil {
|
for _, rawLine := range lines {
|
||||||
session.Rollback()
|
line := strings.TrimSpace(rawLine)
|
||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "文件创建失败!"})
|
if line == "" {
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
defer f.Close()
|
line = strings.ReplaceAll(line, ",", ",")
|
||||||
|
|
||||||
r := csv.NewReader(f)
|
parts := strings.Split(line, ",")
|
||||||
rs, err := r.ReadAll()
|
if len(parts) != 2 {
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "文件解析失败!"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, rr := range rs {
|
|
||||||
if len(rr) != 2 || rr[0] == "" || rr[1] == "" {
|
|
||||||
session.Rollback()
|
session.Rollback()
|
||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "文件解析失败!"})
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "文本解析失败,请检查每行格式是否为 卡片ID,技能等级"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
skLv, err := strconv.Atoi(rr[1])
|
unitNumber := strings.TrimSpace(parts[0])
|
||||||
|
skillLevelRaw := strings.TrimSpace(parts[1])
|
||||||
|
if unitNumber == "" || skillLevelRaw == "" {
|
||||||
|
session.Rollback()
|
||||||
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "文本解析失败,请检查每行格式是否为 卡片ID,技能等级"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
skLv, err := strconv.Atoi(skillLevelRaw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.Rollback()
|
session.Rollback()
|
||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "文件解析失败!"})
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "文本解析失败,请检查每行格式是否为 卡片ID,技能等级"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
uData := unitmodel.CommonUnitData{}
|
uData := unitmodel.CommonUnitData{}
|
||||||
exists, err := session.Table(new(unitmodel.CommonUnitData)).Where("unit_number = ?", rr[0]).Get(&uData)
|
exists, err := session.Table(new(unitmodel.CommonUnitData)).Where("unit_number = ?", unitNumber).Get(&uData)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "卡片查询失败!"})
|
||||||
|
return
|
||||||
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
session.Rollback()
|
session.Rollback()
|
||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "卡片不存在!"})
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "卡片不存在!"})
|
||||||
@@ -102,12 +103,12 @@ func upload(ctx *gin.Context) {
|
|||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "卡片添加失败!"})
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "卡片添加失败!"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err = session.Commit(); err != nil {
|
if err := session.Commit(); err != nil {
|
||||||
session.Rollback()
|
session.Rollback()
|
||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "卡片添加失败!"})
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 1, Msg: "卡片添加失败!"})
|
||||||
return
|
return
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, ErrMsg{Error: 0, Msg: "导入成功,请重新打开游戏!"})
|
ctx.JSON(http.StatusOK, ErrMsg{Error: 0, Msg: "导入成功,请重新打开游戏!"})
|
||||||
|
|||||||
@@ -23,9 +23,10 @@
|
|||||||
<div class="layui-body">
|
<div class="layui-body">
|
||||||
<form class="layui-form layui-col-md6" action="">
|
<form class="layui-form layui-col-md6" action="">
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
<label class="layui-form-label">文件</label>
|
<label class="layui-form-label">内容</label>
|
||||||
<div class="layui-input-block">
|
<div class="layui-input-block">
|
||||||
<button type="button" name="file" class="layui-btn layui-btn-normal" id="test8">选择文件</button>
|
<textarea name="content" id="card-content" placeholder="每行一个,格式:卡片ID,技能等级 例如:3885,8"
|
||||||
|
class="layui-textarea" style="min-height: 220px;"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item">
|
||||||
@@ -39,8 +40,8 @@
|
|||||||
<li>从 <a href="https://card.niconi.co.ni/" target="_blank">LLSIF
|
<li>从 <a href="https://card.niconi.co.ni/" target="_blank">LLSIF
|
||||||
查卡器</a> 查询需要导入的卡片 ID,卡片信息上的 No.xxx 数字。
|
查卡器</a> 查询需要导入的卡片 ID,卡片信息上的 No.xxx 数字。
|
||||||
</li>
|
</li>
|
||||||
<li>使用任意文本编辑器创建一个 .txt 文件,按照<b>卡片 ID,技能等级</b>的格式(例如 SDS 果,技能 8 级则填入
|
<li>在输入框中按<b>卡片 ID,技能等级</b>的格式(例如 SDS 果,技能 8 级则填入
|
||||||
3885,8)填入需要导入的卡片,每张卡片单独一行。</li>
|
3885,8)填写需要导入的卡片,每张卡片单独一行。</li>
|
||||||
<li>分隔符逗号为<b>半角 ,</b> 而非<b>全角 ,</b>。</li>
|
<li>分隔符逗号为<b>半角 ,</b> 而非<b>全角 ,</b>。</li>
|
||||||
<li>仅需要设置技能等级,卡片默认等级MAX,宝石请在游戏内设置。</li>
|
<li>仅需要设置技能等级,卡片默认等级MAX,宝石请在游戏内设置。</li>
|
||||||
<li>仅支持导入UR卡片。</li>
|
<li>仅支持导入UR卡片。</li>
|
||||||
@@ -63,20 +64,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<script src="/static/js/layui.js"></script>
|
<script src="/static/js/layui.js"></script>
|
||||||
<script>
|
<script>
|
||||||
layui.use(['upload', 'layer'], function () {
|
layui.use(['layer'], function () {
|
||||||
var $ = layui.jquery
|
var $ = layui.jquery
|
||||||
, upload = layui.upload
|
|
||||||
, layer = layui.layer;
|
, layer = layui.layer;
|
||||||
|
|
||||||
upload.render({
|
$("#test9").click(function () {
|
||||||
elem: '#test8'
|
const content = $("#card-content").val();
|
||||||
, url: '/admin/upload' // 此处配置你自己的上传接口即可
|
$.post("/admin/upload", { content: content }, function (res) {
|
||||||
, auto: false
|
|
||||||
, accept: 'file' // 普通文件
|
|
||||||
, size: 50 // 限制文件大小,单位 KB
|
|
||||||
, bindAction: '#test9'
|
|
||||||
, done: function (res) {
|
|
||||||
layer.msg(res.msg);
|
layer.msg(res.msg);
|
||||||
|
if (res.error == 0) {
|
||||||
|
$("#card-content").val("");
|
||||||
|
}
|
||||||
|
}).fail(function () {
|
||||||
|
layer.msg("请求失败,请稍后再试");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user