订单写入数据库

This commit is contained in:
2026-02-09 20:43:55 +08:00
parent 2bdbe0f041
commit 357b505275
6 changed files with 165 additions and 48 deletions
+16
View File
@@ -5,6 +5,7 @@ import (
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"regexp" "regexp"
"strings"
"time" "time"
) )
@@ -23,6 +24,15 @@ func GetCurrentTimeString(format ...string) string {
return time.Now().Format(layout) return time.Now().Format(layout)
} }
func StringToTimePtr(str string) (*time.Time, error) {
layout := "2006-01-02 15:04"
t, err := time.Parse(layout, str)
if err != nil {
return nil, err
}
return &t, nil
}
func RandStr32() string { func RandStr32() string {
// 生成 32 字节 (256 位) 随机数据 // 生成 32 字节 (256 位) 随机数据
b := make([]byte, 32) b := make([]byte, 32)
@@ -90,3 +100,9 @@ func IsEmailValid(email string) bool {
regex := regexp.MustCompile(pattern) regex := regexp.MustCompile(pattern)
return regex.MatchString(email) return regex.MatchString(email)
} }
// 判断字符串是否包含标点符号
func IsContainsSpecialChar(str string) bool {
specialChars := "!@#$%^&*()-+={}[]|\\:;\"'<>,.?/"
return strings.ContainsAny(str, specialChars)
}
+26 -12
View File
@@ -71,7 +71,7 @@ type TabUserInfo_ struct {
type TabCookie_ struct { type TabCookie_ struct {
ID uint `gorm:"primaryKey;autoIncrement"` ID uint `gorm:"primaryKey;autoIncrement"`
UserID uint `gorm:"size:16;not null"` UserID uint `gorm:"not null"`
Name string `gorm:"size:255;not null;index"` Name string `gorm:"size:255;not null;index"`
Value string `gorm:"size:255;not null;index"` Value string `gorm:"size:255;not null;index"`
ExpiresAt time.Time `gorm:"type:datetime;index"` ExpiresAt time.Time `gorm:"type:datetime;index"`
@@ -91,23 +91,33 @@ type APIRequestLog_ struct {
} }
type TabPurchaseOrder struct { type TabPurchaseOrder struct {
ID uint `gorm:"primarykey" json:"id"` ID uint `gorm:"primarykey"`
Title string `gorm:"size:200;comment:标题" json:"title"` UserID uint `gorm:"not null"`
Remark string `gorm:"type:text;comment:备注" json:"remark"` Title string `gorm:"size:200;comment:标题"`
Photos datatypes.JSON `gorm:"type:json;comment:照片哈希数组" json:"photos"` Remark string `gorm:"type:text;comment:备注"`
Link string `gorm:"size:1000;comment:链接" json:"link"` Photos datatypes.JSON `gorm:"type:json;comment:照片哈希数组"`
PartName string `gorm:"size:200;not null;comment:物品名称" json:"part_name"` Link string `gorm:"size:1000;comment:链接"`
Styles datatypes.JSON `gorm:"type:json;comment:样式数组" json:"styles"` PartName string `gorm:"size:200;not null;comment:物品名称"`
Costs datatypes.JSON `gorm:"type:json;comment:费用明细数组" json:"costs"` Styles string `gorm:"type:text;comment:样式数组"`
UpdateTime *time.Time `gorm:"type:datetime;autoUpdateTime;comment:更新时间" json:"update_time"` //Costs datatypes.JSON `gorm:"type:json;comment:费用明细数组"`
TrackingNumber string `gorm:"size:100;uniqueIndex;comment:快递单号" json:"tracking_number"` UpdateTime *time.Time `gorm:"type:datetime;autoUpdateTime;comment:更新时间"`
OrderStatus int8 `gorm:"default:1;comment:订单状态" json:"order_status"` TrackingNumber string `gorm:"size:100;Index;comment:快递单号"`
OrderStatus string `gorm:"default:1;comment:订单状态"`
CreatedAt *time.Time `gorm:"type:datetime;autoCreateTime"` CreatedAt *time.Time `gorm:"type:datetime;autoCreateTime"`
UpdatedAt *time.Time `gorm:"type:datetime;autoUpdateTime"` UpdatedAt *time.Time `gorm:"type:datetime;autoUpdateTime"`
DeletedAt gorm.DeletedAt `gorm:"index"` DeletedAt gorm.DeletedAt `gorm:"index"`
} }
type TabPurchaseCosts struct {
ID uint `gorm:"primarykey"`
OrderID uint `gorm:"not null"`
UserID uint `gorm:"not null"`
Price int `gorm:"not null"`
Quantity int `gorm:"not null"`
CreatedAt *time.Time `gorm:"type:datetime;autoCreateTime"`
}
func DatabaseInit() error { func DatabaseInit() error {
var err error var err error
fmt.Println("database_init") fmt.Println("database_init")
@@ -149,5 +159,9 @@ func DatabaseInit() error {
DB.AutoMigrate(&APIRequestLog_{}) DB.AutoMigrate(&APIRequestLog_{})
DB.AutoMigrate(&TabPurchaseOrder{})
DB.AutoMigrate(&TabPurchaseCosts{})
return nil return nil
} }
+79 -11
View File
@@ -1,28 +1,30 @@
package routers package routers
import ( import (
"fmt" "encoding/json"
"ops/models"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"gorm.io/datatypes"
) )
type CostItem struct { type CostItem struct {
Cost float64 `json:"cost" binding:"required,min=0"` // 必须,非负 Cost int `json:"cost"` // 必须,非负
CostT float64 `json:"cost_t" binding:"required,min=0"` // 必须,非负 CostT int `json:"costt"` // 必须,非负
CurrencyType string `json:"currency_type" binding:"required"` // 必须 CurrencyType string `json:"currencytype"` // 必须
Int int `json:"int" binding:"required"` // 必须 Int int `json:"int"` // 必须
Type string `json:"type" binding:"required"` // 必须 Type string `json:"type"` // 必须
} }
type From_purchase_addorder struct { type From_purchase_addorder struct {
Costs []CostItem `json:"costs"` // Costs []CostItem `json:"costs"` //
Link string `json:"link"` // 可选 Link string `json:"link"` // 可选
OrderStatus string `json:"order_status" binding:"required"` // OrderStatus string `json:"order_status"` //
PartName string `json:"part_name"` // 可选 PartName string `json:"partname"` // 可选
Photos []string `json:"photos"` // 可选 Photos []string `json:"photos"` // 可选
Remark string `json:"remark"` // 可选 Remark string `json:"remark"` // 可选
Styles string `json:"styles"` // 可选 Styles string `json:"styles"` // 可选
Title string `json:"title" binding:"required"` // 必须 Title string `json:"title"` // 必须
TrackingNumber string `json:"tracking_number"` // 可选 TrackingNumber string `json:"tracking_number"` // 可选
UpdateTime string `json:"update_time"` // 可选 UpdateTime string `json:"update_time"` // 可选
} }
@@ -35,12 +37,78 @@ func ApiPurchase(r *gin.RouterGroup) {
//需要处理提交的数据,接口有固定的数据格式,不允许乱搞 //需要处理提交的数据,接口有固定的数据格式,不允许乱搞
//fmt.Println(isAuth) //fmt.Println(isAuth)
fmt.Println(user) //fmt.Println(user)
//DebugPrintJson(data) //DebugPrintJson(data)
var jsondata From_purchase_addorder var jsondata From_purchase_addorder
if err := mapstructure.Decode(data, &jsondata); err == nil { if err := mapstructure.Decode(data, &jsondata); err == nil {
fmt.Println("转换后数据:\n", jsondata) //fmt.Println("转换后数据:\n", jsondata)
//数据比较混乱 在这里校验
//判断标题不为空
is_data_ok := true
if jsondata.Title == "" {
is_data_ok = false
}
//判断数量与价格是否为负数
for i := 0; i < len(jsondata.Costs); i++ {
if jsondata.Costs[i].Cost <= 0 {
is_data_ok = false
}
if jsondata.Costs[i].Int <= 0 {
is_data_ok = false
}
}
//判断图片是否为哈希值
for i := 0; i < len(jsondata.Photos); i++ {
//判断字符串是否包含标点符号
if models.IsContainsSpecialChar(jsondata.Photos[i]) {
is_data_ok = false
}
}
//判断时间字符串是否合法
uptime, e := models.StringToTimePtr(jsondata.UpdateTime)
if e != nil {
is_data_ok = false
}
if is_data_ok {
//校验通过
//载入数据库
photos, _ := json.Marshal(jsondata.Photos) //把图片数组转换成字符串
new_data := models.TabPurchaseOrder{
UserID: user.ID,
Title: jsondata.Title,
Remark: jsondata.Remark,
Photos: datatypes.JSON(photos),
Link: jsondata.Link,
PartName: jsondata.PartName,
Styles: jsondata.Styles,
UpdateTime: uptime,
TrackingNumber: jsondata.TrackingNumber,
OrderStatus: jsondata.OrderStatus,
}
models.DB.Create(&new_data)
for i := 0; i < len(jsondata.Costs); i++ {
new_cost_data := models.TabPurchaseCosts{
Price: jsondata.Costs[i].Cost,
Quantity: jsondata.Costs[i].Int,
UserID: user.ID,
OrderID: new_data.ID,
}
models.DB.Create(&new_cost_data)
}
} else {
ReturnJson(ctx, "jsonErr", nil)
}
} else { } else {
ReturnJson(ctx, "jsonErr", nil) ReturnJson(ctx, "jsonErr", nil)
+1
View File
@@ -80,6 +80,7 @@
"currency": "Currency", "currency": "Currency",
"operation": "Operation", "operation": "Operation",
"remove": "Remove", "remove": "Remove",
"change": "Change",
"fee_type": "Fee type", "fee_type": "Fee type",
"input_quantity": "Quantity", "input_quantity": "Quantity",
"input_fee": "Fee", "input_fee": "Fee",
+1
View File
@@ -80,6 +80,7 @@
"currency": "货币", "currency": "货币",
"operation": "操作", "operation": "操作",
"remove": "移除", "remove": "移除",
"change": "修改",
"fee_type": "费用类型", "fee_type": "费用类型",
"input_quantity": "数量", "input_quantity": "数量",
"input_fee": "费用", "input_fee": "费用",
@@ -79,19 +79,29 @@ const cost_sheet = reactive({
}); });
function del_cost(key) { function del_cost(key) {
cost_sheet.type = cost_sheet_tab[key].type;
cost_sheet.int = cost_sheet_tab[key].int;
cost_sheet.cost = cost_sheet_tab[key].cost;
cost_sheet.cost_t = cost_sheet_tab[key].cost_t;
cost_sheet.currency_type = cost_sheet_tab[key].currency_type;
cost_sheet_tab.splice(key, 1); cost_sheet_tab.splice(key, 1);
} }
function add_cost() { function add_cost() {
if (cost_sheet.cost <= 0) {
} else {
// 四舍五入到2位小数 // 四舍五入到2位小数
// const fixed = parseFloat(newVal).toFixed(2);
// if (parseFloat(fixed) !== newVal) {
// cost_sheet.cost = parseFloat(fixed);
// }
var t = parseFloat((cost_sheet.int * cost_sheet.cost).toFixed(2)); var t = parseFloat((cost_sheet.int * cost_sheet.cost).toFixed(2));
cost_sheet.cost_t = t; cost_sheet.cost_t = t;
cost_sheet_tab.push(JSON.parse(JSON.stringify(cost_sheet))); cost_sheet_tab.push(JSON.parse(JSON.stringify(cost_sheet)));
cost_sheet.type = "1";
cost_sheet.int = 1;
cost_sheet.cost = 0.0;
cost_sheet.cost_t = 0.0;
cost_sheet.currency_type = "1";
}
} }
const submit_sheet = reactive({ const submit_sheet = reactive({
@@ -99,12 +109,12 @@ const submit_sheet = reactive({
remark: "", remark: "",
photos: [], photos: [],
link: "", link: "",
part_name: "", partname: "",
styles: "", styles: "",
costs: [], costs: [],
update_time: "", updatetime: "",
tracking_number: "", trackingnumber: "",
order_status: "1", orderstatus: "1",
}); });
function submit_order() { function submit_order() {
@@ -130,7 +140,14 @@ function submit_order() {
//载入价格表 //载入价格表
submit_sheet.costs = []; submit_sheet.costs = [];
for (var i = 0; i < cost_sheet_tab.length; i++) { for (var i = 0; i < cost_sheet_tab.length; i++) {
submit_sheet.costs.push(cost_sheet_tab[i]); //var t=cost_sheet_tab[i]
submit_sheet.costs.push(JSON.parse(JSON.stringify(cost_sheet_tab[i])));
}
//修改价格表里的小数,将所有价值*100去掉小数
for (var i = 0; i < submit_sheet.costs.length; i++) {
submit_sheet.costs[i].cost *= 100;
submit_sheet.costs[i].cost_t *= 100;
} }
console.log(submit_sheet); console.log(submit_sheet);
@@ -262,7 +279,7 @@ watch(
class="form-control" class="form-control"
name="example-text-input" name="example-text-input"
:placeholder="t('purchase_addorder.part_name')" :placeholder="t('purchase_addorder.part_name')"
v-model="submit_sheet.part_name" v-model="submit_sheet.partname"
/> />
</div> </div>
<div class="mt-3"> <div class="mt-3">
@@ -313,7 +330,7 @@ watch(
class="btn btn-outline-danger" class="btn btn-outline-danger"
@click="del_cost(key)" @click="del_cost(key)"
> >
{{ t("purchase_addorder.remove") }} {{ t("purchase_addorder.change") }}
</button> </button>
</td> </td>
</tr> </tr>
@@ -409,7 +426,7 @@ watch(
t("purchase_addorder.update_time") t("purchase_addorder.update_time")
}}</label> }}</label>
<dateTimePicker <dateTimePicker
v-model="submit_sheet.update_time" v-model="submit_sheet.updatetime"
></dateTimePicker> ></dateTimePicker>
</div> </div>
<div class="col-xl-4"> <div class="col-xl-4">
@@ -422,7 +439,7 @@ watch(
:placeholder=" :placeholder="
t('purchase_addorder.input_tracking_number') t('purchase_addorder.input_tracking_number')
" "
v-model="submit_sheet.tracking_number" v-model="submit_sheet.trackingnumber"
/> />
</div> </div>
<div class="col-xl-4"> <div class="col-xl-4">
@@ -431,7 +448,7 @@ watch(
ref="select_beast" ref="select_beast"
class="form-control" class="form-control"
autocompvare="off" autocompvare="off"
v-model="submit_sheet.order_status" v-model="submit_sheet.orderstatus"
> >
<option v-for="(value, key) in order_status" :value="key"> <option v-for="(value, key) in order_status" :value="key">
{{ value }} {{ value }}