up
This commit is contained in:
@@ -68,6 +68,7 @@ func main() {
|
|||||||
models.ConfigAllInit()
|
models.ConfigAllInit()
|
||||||
routers.ApiUserInit() //用户表先初始化这是必须的因为后面需要用到用户组
|
routers.ApiUserInit() //用户表先初始化这是必须的因为后面需要用到用户组
|
||||||
routers.ApiScheduleInit()
|
routers.ApiScheduleInit()
|
||||||
|
routers.ApiPurchaseInit()
|
||||||
|
|
||||||
//创建必要目录
|
//创建必要目录
|
||||||
for _, path := range models.ConfigsFile.Pahts {
|
for _, path := range models.ConfigsFile.Pahts {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/glebarez/sqlite"
|
"github.com/glebarez/sqlite"
|
||||||
"gorm.io/datatypes"
|
|
||||||
"gorm.io/driver/mysql"
|
"gorm.io/driver/mysql"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -90,34 +89,6 @@ type APIRequestLog_ struct {
|
|||||||
CreatedAt time.Time `gorm:"column:created_at;type:datetime;default:CURRENT_TIMESTAMP" json:"created_at"`
|
CreatedAt time.Time `gorm:"column:created_at;type:datetime;default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TabPurchaseOrder struct {
|
|
||||||
ID uint `gorm:"primarykey"`
|
|
||||||
UserID uint `gorm:"not null"`
|
|
||||||
Title string `gorm:"size:200;comment:标题"`
|
|
||||||
Remark string `gorm:"type:text;comment:备注"`
|
|
||||||
Photos datatypes.JSON `gorm:"type:json;comment:照片哈希数组"`
|
|
||||||
Link string `gorm:"size:1000;comment:链接"`
|
|
||||||
PartName string `gorm:"size:200;not null;comment:物品名称"`
|
|
||||||
Styles string `gorm:"type:text;comment:样式数组"`
|
|
||||||
//Costs datatypes.JSON `gorm:"type:json;comment:费用明细数组"`
|
|
||||||
UpdateTime *time.Time `gorm:"type:datetime;autoUpdateTime;comment:更新时间"`
|
|
||||||
TrackingNumber string `gorm:"size:100;Index;comment:快递单号"`
|
|
||||||
OrderStatus string `gorm:"default:1;comment:订单状态"`
|
|
||||||
|
|
||||||
CreatedAt *time.Time `gorm:"type:datetime;autoCreateTime"`
|
|
||||||
UpdatedAt *time.Time `gorm:"type:datetime;autoUpdateTime"`
|
|
||||||
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")
|
||||||
@@ -159,9 +130,5 @@ func DatabaseInit() error {
|
|||||||
|
|
||||||
DB.AutoMigrate(&APIRequestLog_{})
|
DB.AutoMigrate(&APIRequestLog_{})
|
||||||
|
|
||||||
DB.AutoMigrate(&TabPurchaseOrder{})
|
|
||||||
|
|
||||||
DB.AutoMigrate(&TabPurchaseCosts{})
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package routers
|
package routers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"ops/models"
|
"ops/models"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"gorm.io/datatypes"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CostItem struct {
|
type CostItem struct {
|
||||||
@@ -21,13 +21,48 @@ 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"` // 订单状态
|
OrderStatus string `json:"order_status"` // 订单状态
|
||||||
PartName string `json:"partname"` // 物件名称
|
//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"` // 标题
|
Title string `json:"title"` // 标题
|
||||||
TrackingNumber string `json:"tracking_number"` // 快递单号
|
//TrackingNumber string `json:"tracking_number"` // 快递单号
|
||||||
UpdateTime string `json:"update_time"` // 更新时间
|
//UpdateTime string `json:"update_time"` // 更新时间
|
||||||
|
}
|
||||||
|
|
||||||
|
type TabPurchaseOrder struct {
|
||||||
|
ID uint `gorm:"primarykey"`
|
||||||
|
UserID uint `gorm:"not null"`
|
||||||
|
Title string `gorm:"size:200;comment:标题"`
|
||||||
|
Remark string `gorm:"type:text;comment:备注"`
|
||||||
|
Link string `gorm:"size:1000;comment:链接"`
|
||||||
|
Styles string `gorm:"type:text;comment:样式数组"`
|
||||||
|
CreatedAt *time.Time `gorm:"type:datetime;autoCreateTime"`
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TabPurchaseFileBind struct {
|
||||||
|
ID uint `gorm:"primarykey"`
|
||||||
|
OrderID uint `gorm:"not null"`
|
||||||
|
FileID uint `gorm:"not null"`
|
||||||
|
CreatedAt *time.Time `gorm:"type:datetime;autoCreateTime"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ApiPurchaseInit() {
|
||||||
|
|
||||||
|
models.DB.AutoMigrate(&TabPurchaseOrder{})
|
||||||
|
models.DB.AutoMigrate(&TabPurchaseCosts{})
|
||||||
|
models.DB.AutoMigrate(&TabPurchaseFileBind{})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApiPurchase(r *gin.RouterGroup) {
|
func ApiPurchase(r *gin.RouterGroup) {
|
||||||
@@ -61,11 +96,11 @@ func ApiPurchase(r *gin.RouterGroup) {
|
|||||||
|
|
||||||
//读取有多少条目
|
//读取有多少条目
|
||||||
var count int64
|
var count int64
|
||||||
models.DB.Model(&models.TabPurchaseOrder{}).Count(&count)
|
models.DB.Model(TabPurchaseOrder{}).Count(&count)
|
||||||
//fmt.Println(count)
|
//fmt.Println(count)
|
||||||
|
|
||||||
//读取条目
|
//读取条目
|
||||||
var getorders []models.TabPurchaseOrder
|
var getorders []TabPurchaseOrder
|
||||||
models.DB.Order("created_at DESC").Offset(jsondata.Entries * (jsondata.Page - 1)).Limit(jsondata.Entries).Find(&getorders)
|
models.DB.Order("created_at DESC").Offset(jsondata.Entries * (jsondata.Page - 1)).Limit(jsondata.Entries).Find(&getorders)
|
||||||
|
|
||||||
ReturnJson(ctx, "apiOK", map[string]interface{}{
|
ReturnJson(ctx, "apiOK", map[string]interface{}{
|
||||||
@@ -97,8 +132,8 @@ func ApiPurchase(r *gin.RouterGroup) {
|
|||||||
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 {
|
||||||
|
|
||||||
jsonStr, _ := json.MarshalIndent(jsondata, "", " ")
|
//jsonStr, _ := json.MarshalIndent(jsondata, "", " ")
|
||||||
fmt.Println("转换后数据:\n", string(jsonStr))
|
//fmt.Println("转换后数据:\n", string(jsonStr))
|
||||||
|
|
||||||
//数据比较混乱 在这里校验
|
//数据比较混乱 在这里校验
|
||||||
|
|
||||||
@@ -106,19 +141,15 @@ func ApiPurchase(r *gin.RouterGroup) {
|
|||||||
is_data_ok := true
|
is_data_ok := true
|
||||||
if jsondata.Title == "" {
|
if jsondata.Title == "" {
|
||||||
is_data_ok = false
|
is_data_ok = false
|
||||||
|
|
||||||
fmt.Println("err1")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//判断数量与价格是否为负数
|
//判断数量与价格是否为负数
|
||||||
for i := 0; i < len(jsondata.Costs); i++ {
|
for i := 0; i < len(jsondata.Costs); i++ {
|
||||||
if jsondata.Costs[i].Cost <= 0 {
|
if jsondata.Costs[i].Cost <= 0 {
|
||||||
is_data_ok = false
|
is_data_ok = false
|
||||||
fmt.Println("err2")
|
|
||||||
}
|
}
|
||||||
if jsondata.Costs[i].Int <= 0 {
|
if jsondata.Costs[i].Int <= 0 {
|
||||||
is_data_ok = false
|
is_data_ok = false
|
||||||
fmt.Println("err3")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,33 +164,30 @@ func ApiPurchase(r *gin.RouterGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//判断时间字符串是否合法
|
//判断时间字符串是否合法
|
||||||
uptime, e := models.StringToTimePtr(jsondata.UpdateTime)
|
// uptime, e := models.StringToTimePtr(jsondata.UpdateTime)
|
||||||
if e != nil {
|
// if e != nil {
|
||||||
is_data_ok = false
|
// is_data_ok = false
|
||||||
fmt.Println("err5")
|
// fmt.Println("err5")
|
||||||
}
|
// }
|
||||||
|
|
||||||
if is_data_ok {
|
if is_data_ok {
|
||||||
//校验通过
|
//校验通过
|
||||||
//载入数据库
|
//载入数据库
|
||||||
|
|
||||||
photos, _ := json.Marshal(jsondata.Photos) //把图片数组转换成字符串
|
//fmt.Println("yes")
|
||||||
new_data := models.TabPurchaseOrder{
|
|
||||||
|
//photos, _ := json.Marshal(jsondata.Photos) //把图片数组转换成字符串
|
||||||
|
new_data := TabPurchaseOrder{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
Title: jsondata.Title,
|
Title: jsondata.Title,
|
||||||
Remark: jsondata.Remark,
|
Remark: jsondata.Remark,
|
||||||
Photos: datatypes.JSON(photos),
|
|
||||||
Link: jsondata.Link,
|
Link: jsondata.Link,
|
||||||
PartName: jsondata.PartName,
|
|
||||||
Styles: jsondata.Styles,
|
Styles: jsondata.Styles,
|
||||||
UpdateTime: uptime,
|
|
||||||
TrackingNumber: jsondata.TrackingNumber,
|
|
||||||
OrderStatus: jsondata.OrderStatus,
|
|
||||||
}
|
}
|
||||||
models.DB.Create(&new_data)
|
models.DB.Create(&new_data)
|
||||||
|
|
||||||
for i := 0; i < len(jsondata.Costs); i++ {
|
for i := 0; i < len(jsondata.Costs); i++ {
|
||||||
new_cost_data := models.TabPurchaseCosts{
|
new_cost_data := TabPurchaseCosts{
|
||||||
Price: jsondata.Costs[i].Cost,
|
Price: jsondata.Costs[i].Cost,
|
||||||
Quantity: jsondata.Costs[i].Int,
|
Quantity: jsondata.Costs[i].Int,
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
@@ -168,6 +196,24 @@ func ApiPurchase(r *gin.RouterGroup) {
|
|||||||
models.DB.Create(&new_cost_data)
|
models.DB.Create(&new_cost_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//绑定文件
|
||||||
|
for i := 0; i < len(jsondata.Photos); i++ {
|
||||||
|
findFile := models.TabFileInfo_{
|
||||||
|
Sha256: jsondata.Photos[i],
|
||||||
|
Type: "image",
|
||||||
|
}
|
||||||
|
if models.DB.Where(&findFile).First(&findFile).Error == nil {
|
||||||
|
bind := TabPurchaseFileBind{
|
||||||
|
OrderID: new_data.ID,
|
||||||
|
FileID: findFile.ID,
|
||||||
|
}
|
||||||
|
models.DB.Create(&bind)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnJson(ctx, "apiOK", nil)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ReturnJson(ctx, "jsonErr_1", nil)
|
ReturnJson(ctx, "jsonErr_1", nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,9 @@ const newCost = reactive({
|
|||||||
currencyType: "1", // 货币类型:默认人民币
|
currencyType: "1", // 货币类型:默认人民币
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 费用验证错误状态:点击添加按钮后发现费用为0时触发
|
||||||
|
const costError = ref(false);
|
||||||
|
|
||||||
// ==================== 表单数据 ====================
|
// ==================== 表单数据 ====================
|
||||||
/**
|
/**
|
||||||
* 订单表单主数据对象
|
* 订单表单主数据对象
|
||||||
@@ -125,12 +128,12 @@ const form = reactive({
|
|||||||
remark: "", // 备注说明
|
remark: "", // 备注说明
|
||||||
photos: [], // 图片列表(上传后由 dropzone 填充)
|
photos: [], // 图片列表(上传后由 dropzone 填充)
|
||||||
link: "", // 采购链接
|
link: "", // 采购链接
|
||||||
partname: "", // 配件名称
|
//partname: "", // 配件名称
|
||||||
styles: "", // 款式标签
|
styles: "", // 款式标签
|
||||||
costs: [], // 费用明细(提交前由 costEntries 转换)
|
costs: [], // 费用明细(提交前由 costEntries 转换)
|
||||||
tracking_number: "", // 快递单号
|
//tracking_number: "", // 快递单号
|
||||||
updatetime: "", // 更新时间
|
//updatetime: "", // 更新时间
|
||||||
order_status: "1", // 订单状态(默认待下单)
|
//order_status: "1", // 订单状态(默认待下单)
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,7 +149,11 @@ const newCostTotal = computed(() =>
|
|||||||
* 条件:单价必须大于0
|
* 条件:单价必须大于0
|
||||||
*/
|
*/
|
||||||
function addCostEntry() {
|
function addCostEntry() {
|
||||||
if (newCost.cost <= 0) return;
|
if (newCost.cost <= 0) {
|
||||||
|
costError.value = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
costError.value = false;
|
||||||
costEntries.push({
|
costEntries.push({
|
||||||
type: newCost.type,
|
type: newCost.type,
|
||||||
int: newCost.int,
|
int: newCost.int,
|
||||||
@@ -178,6 +185,8 @@ watch(
|
|||||||
(val) => {
|
(val) => {
|
||||||
const fixed = parseFloat(val).toFixed(2);
|
const fixed = parseFloat(val).toFixed(2);
|
||||||
if (parseFloat(fixed) !== val) newCost.cost = parseFloat(fixed);
|
if (parseFloat(fixed) !== val) newCost.cost = parseFloat(fixed);
|
||||||
|
// 用户开始输入时清除错误状态
|
||||||
|
if (val > 0) costError.value = false;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -205,10 +214,11 @@ async function handleSubmit() {
|
|||||||
|
|
||||||
// 从 dropzone 组件获取已上传的图片文件名
|
// 从 dropzone 组件获取已上传的图片文件名
|
||||||
form.photos = [];
|
form.photos = [];
|
||||||
if (photosRef.value?.has_some_files) {
|
// if (photosRef.value?.has_some_files) {
|
||||||
const result = photosRef.value.get_some_files();
|
// const result = photosRef.value.get_some_files();
|
||||||
form.photos = result.map((f) => f.name);
|
// form.photos = result.map((f) => f.name);
|
||||||
}
|
// }
|
||||||
|
form.photos=photosRef.value?.return_files().map((f)=>f.hash);
|
||||||
|
|
||||||
// 将费用明细转换为提交格式
|
// 将费用明细转换为提交格式
|
||||||
// 注意:金额需要从"元"转为"分"(乘以100)存储
|
// 注意:金额需要从"元"转为"分"(乘以100)存储
|
||||||
@@ -219,23 +229,29 @@ async function handleSubmit() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
// 开始 loading
|
// 开始 loading
|
||||||
loading.value = true;
|
console.log(form)
|
||||||
try {
|
purchaseApi.addOrder(form).then((r)=>{
|
||||||
// 调用采购 API 添加订单
|
|
||||||
const { errCode } = await purchaseApi.addOrder(form);
|
console.log(r)
|
||||||
if (errCode === 0) {
|
|
||||||
// 保存成功,显示成功提示
|
})
|
||||||
toast.success(t("message.save_ok"));
|
// loading.value = true;
|
||||||
} else {
|
// try {
|
||||||
// 服务器错误,显示错误提示
|
// // 调用采购 API 添加订单
|
||||||
toast.error(t("message.server_error"));
|
// const { errCode } = await purchaseApi.addOrder(form);
|
||||||
}
|
// if (errCode === 0) {
|
||||||
} catch {
|
// // 保存成功,显示成功提示
|
||||||
// 错误已被 HTTP 拦截器处理,此处无需额外处理
|
// toast.success(t("message.save_ok"));
|
||||||
} finally {
|
// } else {
|
||||||
// 无论成功失败,都要关闭 loading
|
// // 服务器错误,显示错误提示
|
||||||
loading.value = false;
|
// toast.error(t("message.server_error"));
|
||||||
}
|
// }
|
||||||
|
// } catch {
|
||||||
|
// // 错误已被 HTTP 拦截器处理,此处无需额外处理
|
||||||
|
// } finally {
|
||||||
|
// // 无论成功失败,都要关闭 loading
|
||||||
|
// loading.value = false;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -371,11 +387,11 @@ async function handleSubmit() {
|
|||||||
<td class="px-3 py-2 text-gray-500">{{ item.cost }}</td>
|
<td class="px-3 py-2 text-gray-500">{{ item.cost }}</td>
|
||||||
<td class="px-3 py-2 text-gray-500">{{ item.costt }}</td>
|
<td class="px-3 py-2 text-gray-500">{{ item.costt }}</td>
|
||||||
<td class="px-3 py-2 text-gray-500">
|
<td class="px-3 py-2 text-gray-500">
|
||||||
<img
|
<!-- <img
|
||||||
:src="currencyFlags[item.currencytype]"
|
:src="currencyFlags[item.currencytype]"
|
||||||
class="inline-block h-4 w-6 align-middle"
|
class="inline-block h-4 w-6 align-middle"
|
||||||
:alt="currencyOptions[item.currencytype]"
|
:alt="currencyOptions[item.currencytype]"
|
||||||
/>
|
/> -->
|
||||||
{{ currencyOptions[item.currencytype] }}
|
{{ currencyOptions[item.currencytype] }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-3 py-2">
|
<td class="px-3 py-2">
|
||||||
@@ -430,7 +446,8 @@ async function handleSubmit() {
|
|||||||
<input
|
<input
|
||||||
v-model="newCost.cost"
|
v-model="newCost.cost"
|
||||||
type="number"
|
type="number"
|
||||||
class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm dark:border-dk-muted dark:bg-dk-base dark:text-white"
|
class="w-full rounded-lg border bg-white px-3 py-2 text-sm dark:bg-dk-base dark:text-white"
|
||||||
|
:class="costError ? 'border-red-500' : 'border-gray-300 dark:border-dk-muted'"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
min="0"
|
min="0"
|
||||||
/>
|
/>
|
||||||
@@ -479,7 +496,7 @@ async function handleSubmit() {
|
|||||||
<useDropzone
|
<useDropzone
|
||||||
acceptFiles="image/*"
|
acceptFiles="image/*"
|
||||||
uploadURL="/api/files/upload/image"
|
uploadURL="/api/files/upload/image"
|
||||||
maxFiles="10"
|
:maxFiles="10"
|
||||||
ref="photosRef"
|
ref="photosRef"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user