还差批量图片上传
This commit is contained in:
@@ -52,6 +52,7 @@ func ApiRoot(r *gin.RouterGroup) {
|
||||
|
||||
ApiStatic(r.Group("/static"))
|
||||
ApiUser(r.Group("/users"))
|
||||
ApiFiles(r.Group("/files"))
|
||||
|
||||
r.GET("/", func(ctx *gin.Context) {
|
||||
ReturnJson(ctx, "apiOK", nil)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package routers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func ApiFiles(r *gin.RouterGroup) {
|
||||
r.POST("/upload", func(ctx *gin.Context) {
|
||||
fmt.Print(ctx.FormFile("file"))
|
||||
ReturnJson(ctx, "apiOK", nil)
|
||||
})
|
||||
r.GET("/upload", func(ctx *gin.Context) {
|
||||
ReturnJson(ctx, "apiOK", nil)
|
||||
})
|
||||
|
||||
}
|
||||
Generated
+115
@@ -30,11 +30,21 @@
|
||||
"axios": "^1.13.2",
|
||||
"bootstrap": "^5.3.8",
|
||||
"cropperjs": "^2.1.0",
|
||||
"dropzone": "^6.0.0-beta.2",
|
||||
"filepond": "^4.32.11",
|
||||
"filepond-plugin-file-validate-type": "^1.2.9",
|
||||
"filepond-plugin-image-crop": "^2.0.6",
|
||||
"filepond-plugin-image-exif-orientation": "^1.0.11",
|
||||
"filepond-plugin-image-preview": "^4.6.12",
|
||||
"filepond-plugin-image-resize": "^2.0.10",
|
||||
"flatpickr": "^4.6.13",
|
||||
"litepicker": "^2.0.12",
|
||||
"pinia": "^3.0.4",
|
||||
"tom-select": "^2.4.3",
|
||||
"vue": "^3.5.22",
|
||||
"vue-cropper": "^0.6.5",
|
||||
"vue-filepond": "^7.0.4",
|
||||
"vue-flatpickr-component": "^12.0.0",
|
||||
"vue-i18n": "^11.1.12",
|
||||
"vue-router": "^4.6.3"
|
||||
},
|
||||
@@ -1883,6 +1893,12 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@swc/helpers": {
|
||||
"version": "0.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.2.14.tgz",
|
||||
"integrity": "sha512-wpCQMhf5p5GhNg2MmGKXzUNwxe7zRiCsmqYsamez2beP7mKPCSiu+BjZcdN95yYSzO857kr0VfQewmGpS77nqA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tabler/core": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@tabler/core/-/core-1.4.0.tgz",
|
||||
@@ -2520,6 +2536,16 @@
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/dropzone": {
|
||||
"version": "6.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/dropzone/-/dropzone-6.0.0-beta.2.tgz",
|
||||
"integrity": "sha512-k44yLuFFhRk53M8zP71FaaNzJYIzr99SKmpbO/oZKNslDjNXQsBTdfLs+iONd0U0L94zzlFzRnFdqbLcs7h9fQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@swc/helpers": "^0.2.13",
|
||||
"just-extend": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
@@ -2684,6 +2710,58 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/filepond": {
|
||||
"version": "4.32.11",
|
||||
"resolved": "https://registry.npmjs.org/filepond/-/filepond-4.32.11.tgz",
|
||||
"integrity": "sha512-+uHkc/XNksMMy2S+x5MGxTuA97NqzBBwmoixn3tqGELa4BgqJ+PBiWL3YeRamqAoYguT7t/au3s7ams2jjMshA==",
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/filepond-plugin-file-validate-type": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/filepond-plugin-file-validate-type/-/filepond-plugin-file-validate-type-1.2.9.tgz",
|
||||
"integrity": "sha512-Tzv07aNdZvjUXDRA3XL16QMEvh6llDrXlcZ6W0eTHQ+taHaVg/JKJTFs/AViO+6ZcpPCcQStbhYEL2HoS+vldw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"filepond": ">=1.x <5.x"
|
||||
}
|
||||
},
|
||||
"node_modules/filepond-plugin-image-crop": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/filepond-plugin-image-crop/-/filepond-plugin-image-crop-2.0.6.tgz",
|
||||
"integrity": "sha512-bSy/KND4EP/QtW8MxIj23qgSEPUVRrT8XdktJ+OU9y8xRjFjTG+qcuw1LsycARQYRtzi8cZrD3P4POOITfkywQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"filepond": ">=3.x <5.x"
|
||||
}
|
||||
},
|
||||
"node_modules/filepond-plugin-image-exif-orientation": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/filepond-plugin-image-exif-orientation/-/filepond-plugin-image-exif-orientation-1.0.11.tgz",
|
||||
"integrity": "sha512-hLBc12Fk6Zkj3L8mSAn+elugHOqT5rLUbgVXQQIQjMe0FsGjtpoxqeVR6jt4IWHGat2L9sFAgU2TGmd1mqosCg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"filepond": ">=3.x <5.x"
|
||||
}
|
||||
},
|
||||
"node_modules/filepond-plugin-image-preview": {
|
||||
"version": "4.6.12",
|
||||
"resolved": "https://registry.npmjs.org/filepond-plugin-image-preview/-/filepond-plugin-image-preview-4.6.12.tgz",
|
||||
"integrity": "sha512-Y8ETX5QVV0mbPB0586UH8AUmG9tZg8PuN5bdEAIlZVJFTct5ebViJ7+Am94/VhTPjLqZjBf1zmDq5JU6XRsZKw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"filepond": ">=4.x <5.x"
|
||||
}
|
||||
},
|
||||
"node_modules/filepond-plugin-image-resize": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/filepond-plugin-image-resize/-/filepond-plugin-image-resize-2.0.10.tgz",
|
||||
"integrity": "sha512-irX+J275u8Ph1KcciCeSQmxeFjbu0+co5XVCkiwdSNnz6KiqrCKN7RXTvEbdgSdDzyi5omr2oP1rKWps5L1RsQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"filepond": ">=3.x <5.x"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
@@ -2698,6 +2776,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/flatpickr": {
|
||||
"version": "4.6.13",
|
||||
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
|
||||
"integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.11",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||
@@ -3011,6 +3095,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/just-extend": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-5.1.1.tgz",
|
||||
"integrity": "sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/kolorist": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
|
||||
@@ -4201,6 +4291,31 @@
|
||||
"integrity": "sha512-lSvY6IpeA/Tv/iPZ/FOkMHVRBPSlm7t57nuHEZFBMRNOH8ElvfqVlnHGDOAMlvPhh9gHiddiQoASS+fY0MFX0g==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/vue-filepond": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-filepond/-/vue-filepond-7.0.4.tgz",
|
||||
"integrity": "sha512-HvWlCG8qjvyykrpPTDjJ+JqsHTXt5/0zWMX9vu7kU3JXCUODPUkGi9prZcauOnIZ4MqyeSZ9M0sDVwdMATyt1g==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"filepond": ">=4.7.4 < 5.x",
|
||||
"vue": ">=3 < 4"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-flatpickr-component": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-flatpickr-component/-/vue-flatpickr-component-12.0.0.tgz",
|
||||
"integrity": "sha512-CJ5jrgTaeD66Z4mjEocSTAdB/n6IGSlUICwdBanpyCI8hswq5rwXvEYQ5IKA3K3uVjP5pBlY9Rg6o3xoszTPpA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"flatpickr": "^4.6.13"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-i18n": {
|
||||
"version": "11.1.12",
|
||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.1.12.tgz",
|
||||
|
||||
@@ -34,11 +34,21 @@
|
||||
"axios": "^1.13.2",
|
||||
"bootstrap": "^5.3.8",
|
||||
"cropperjs": "^2.1.0",
|
||||
"dropzone": "^6.0.0-beta.2",
|
||||
"filepond": "^4.32.11",
|
||||
"filepond-plugin-file-validate-type": "^1.2.9",
|
||||
"filepond-plugin-image-crop": "^2.0.6",
|
||||
"filepond-plugin-image-exif-orientation": "^1.0.11",
|
||||
"filepond-plugin-image-preview": "^4.6.12",
|
||||
"filepond-plugin-image-resize": "^2.0.10",
|
||||
"flatpickr": "^4.6.13",
|
||||
"litepicker": "^2.0.12",
|
||||
"pinia": "^3.0.4",
|
||||
"tom-select": "^2.4.3",
|
||||
"vue": "^3.5.22",
|
||||
"vue-cropper": "^0.6.5",
|
||||
"vue-filepond": "^7.0.4",
|
||||
"vue-flatpickr-component": "^12.0.0",
|
||||
"vue-i18n": "^11.1.12",
|
||||
"vue-router": "^4.6.3"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<script setup>
|
||||
import { onMounted, ref, watch, defineProps,reactive } from "vue";
|
||||
|
||||
import flatpickr from "flatpickr";
|
||||
import 'flatpickr/dist/flatpickr.css';
|
||||
import 'flatpickr/dist/l10n/zh.js';
|
||||
|
||||
import { useI18n } from "vue-i18n";
|
||||
const { t, locale } = useI18n();
|
||||
|
||||
|
||||
const datatimepack=ref()
|
||||
|
||||
const datatimepack_config=reactive({
|
||||
|
||||
enableTime: true,
|
||||
dateFormat: "Y-m-d H:i",
|
||||
minuteIncrement:1,
|
||||
time_24hr: true
|
||||
//locale:"zh"
|
||||
|
||||
})
|
||||
|
||||
const sele_data=reactive()
|
||||
|
||||
function getCurrentDateTime() {
|
||||
const now = new Date();
|
||||
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
|
||||
watch(locale, () => {
|
||||
if(locale.value=="zh-CN"){
|
||||
datatimepack_config.locale='zh'
|
||||
}else{
|
||||
datatimepack_config.locale='en'
|
||||
}
|
||||
//console.log(locale.value=="zh-CN"?"zh":"en")
|
||||
});
|
||||
|
||||
const prop= defineProps({
|
||||
setdef: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
onMounted(() => {
|
||||
// @formatter:off
|
||||
//console.log(getCurrentDateTime())
|
||||
//sele_data=getCurrentDateTime();
|
||||
|
||||
// console.log(prop.setdef)
|
||||
|
||||
if(prop.setdef=="")
|
||||
{
|
||||
datatimepack_config.defaultDate=getCurrentDateTime()
|
||||
}else{
|
||||
datatimepack_config.defaultDate=prop.setdef
|
||||
}
|
||||
|
||||
datatimepack_config.locale=locale.value=="zh-CN"?"zh":"en";
|
||||
flatpickr(datatimepack.value, datatimepack_config);
|
||||
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
<div ></div>
|
||||
<input ref="datatimepack" type="datetime-local" class="form-control" v-model="sele_data">
|
||||
|
||||
</template>
|
||||
@@ -0,0 +1,133 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import Dropzone from 'dropzone'
|
||||
import 'dropzone/dist/dropzone.css'
|
||||
|
||||
const dropzoneElement = ref(null)
|
||||
let dropzoneInstance = null
|
||||
const files = ref([])
|
||||
|
||||
// 初始化 Dropzone
|
||||
const initDropzone = () => {
|
||||
if (!dropzoneElement.value) return
|
||||
|
||||
// 禁用自动发现
|
||||
Dropzone.autoDiscover = false
|
||||
|
||||
// 移除任何现有的 Dropzone 实例
|
||||
if (dropzoneInstance) {
|
||||
dropzoneInstance.destroy()
|
||||
}
|
||||
|
||||
// 初始化新的实例
|
||||
dropzoneInstance = new Dropzone(dropzoneElement.value, {
|
||||
url: '/api/files/upload', // 上传地址
|
||||
method: 'post',
|
||||
// 确保不启用分片上传
|
||||
// chunking: false, // 明确禁用分片
|
||||
// forceChunking: false, // 强制不分片
|
||||
// chunkSize: false, // 不分片大小
|
||||
// retryChunks: false, // 不重试分片
|
||||
// parallelChunkUploads: false, // 不并行上传分片
|
||||
|
||||
parallelUploads: 1, // 同时上传的文件数
|
||||
maxFilesize: 10, // MB
|
||||
maxFiles: 5, // 最大文件数
|
||||
acceptedFiles: 'image/*,.pdf,.doc,.docx', // 接受的文件类型
|
||||
addRemoveLinks: true, // 显示移除链接
|
||||
dictDefaultMessage: '拖放文件到这里或点击上传',
|
||||
dictFallbackMessage: '您的浏览器不支持拖放文件上传',
|
||||
dictFileTooBig: '文件太大 ({{filesize}}MB). 最大文件大小: {{maxFilesize}}MB.',
|
||||
dictInvalidFileType: '不支持此文件类型',
|
||||
dictResponseError: '服务器响应错误 {{statusCode}}',
|
||||
dictCancelUpload: '取消上传',
|
||||
dictUploadCanceled: '上传已取消',
|
||||
dictCancelUploadConfirmation: '确定要取消上传吗?',
|
||||
dictRemoveFile: '移除文件',
|
||||
dictMaxFilesExceeded: '您最多只能上传 {{maxFiles}} 个文件',
|
||||
|
||||
// 事件处理
|
||||
init: function() {
|
||||
this.on('success', (file, response) => {
|
||||
console.log('上传成功:', file.name, response)
|
||||
}),
|
||||
this.on('error', (file, errorMessage) => {
|
||||
console.error('上传失败:', file.name, errorMessage)
|
||||
}),
|
||||
this.on('removedfile', (file) => {
|
||||
console.log('remove:')
|
||||
files.value = files.value.filter(f => f.name !== file.name)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 自定义方法
|
||||
const formatBytes = (bytes, decimals = 2) => {
|
||||
if (bytes === 0) return '0 Bytes'
|
||||
const k = 1024
|
||||
const dm = decimals < 0 ? 0 : decimals
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
|
||||
}
|
||||
|
||||
// 手动添加文件的方法
|
||||
const addFiles = (fileList) => {
|
||||
if (dropzoneInstance) {
|
||||
Array.from(fileList).forEach(file => {
|
||||
dropzoneInstance.addFile(file)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 获取所有已添加的文件
|
||||
const getAllFiles = () => {
|
||||
return dropzoneInstance ? dropzoneInstance.files : []
|
||||
}
|
||||
|
||||
// 清除所有文件
|
||||
const removeAllFiles = () => {
|
||||
if (dropzoneInstance) {
|
||||
dropzoneInstance.removeAllFiles(true)
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载时初始化
|
||||
onMounted(() => {
|
||||
initDropzone()
|
||||
})
|
||||
|
||||
// 组件卸载时销毁
|
||||
onUnmounted(() => {
|
||||
if (dropzoneInstance) {
|
||||
dropzoneInstance.destroy()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div ref="dropzoneElement" class="dropzone"></div>
|
||||
<div v-if="files.length > 0" class="mt-4">
|
||||
<h3>已选择的文件:</h3>
|
||||
<ul>
|
||||
<li v-for="file in files" :key="file.name">
|
||||
{{ file.name }} ({{ formatBytes(file.size) }})
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.dropzone {
|
||||
border: 2px dashed #cccccc;
|
||||
border-radius: 5px;
|
||||
background: white;
|
||||
padding: 20px;
|
||||
min-height: 150px;
|
||||
}
|
||||
</style>
|
||||
@@ -154,5 +154,19 @@
|
||||
"license": "License",
|
||||
"source_code": "Source Code",
|
||||
"copy": "Copyright © 2025 Operations. All rights reserved."
|
||||
},
|
||||
"cost_type":{
|
||||
"unit_price":"Unit Price",
|
||||
"freight":"Freight"
|
||||
},
|
||||
"order_status": {
|
||||
"pending_order": "Pending Order",
|
||||
"order_placed": "Order Placed",
|
||||
"in_transit": "In Transit",
|
||||
"completed": "Completed",
|
||||
"refund_requested": "Refund Requested",
|
||||
"returning": "Returning",
|
||||
"refunded": "Refunded",
|
||||
"lost_package": "Lost Package"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
"purchase": "采购",
|
||||
"warehouse": "仓库"
|
||||
},
|
||||
"tagadder":{
|
||||
"not_fund_item":"没有找到匹配项",
|
||||
"loding":"正在加载...",
|
||||
"add":"添加新选项: "
|
||||
"tagadder": {
|
||||
"not_fund_item": "没有找到匹配项",
|
||||
"loding": "正在加载...",
|
||||
"add": "添加新选项: "
|
||||
},
|
||||
"cropper": {
|
||||
"select_image": "选择图片",
|
||||
@@ -154,5 +154,19 @@
|
||||
"license": "协议",
|
||||
"source_code": "源码",
|
||||
"copy": "版权 © 2025 Operations. 保留所有权利。"
|
||||
},
|
||||
"cost_type": {
|
||||
"unit_price": "单价",
|
||||
"freight": "运费"
|
||||
},
|
||||
"order_status": {
|
||||
"pending_order": "待下单",
|
||||
"order_placed": "已下单",
|
||||
"in_transit": "运输中",
|
||||
"completed": "已完成",
|
||||
"refund_requested": "申请退款",
|
||||
"returning": "退回中",
|
||||
"refunded": "已退款",
|
||||
"lost_package": "丢件"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup>
|
||||
import { onMounted, watch, ref ,reactive} from "vue";
|
||||
import { onMounted, watch, ref, reactive } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
import tagadder from "@/components/tagadder.vue";
|
||||
import datePicker from "@/components/datePicker.vue";
|
||||
import dateTimePicker from "@/components/dateTimePicker.vue";
|
||||
|
||||
import TomSelect from "tom-select";
|
||||
import "tom-select/dist/css/tom-select.css";
|
||||
@@ -14,47 +14,69 @@ function functionupdataTitle() {
|
||||
document.title = "Operations." + t("purchase.add_part");
|
||||
}
|
||||
|
||||
//货币类型
|
||||
const currency_type = reactive({
|
||||
1: "RMB",
|
||||
2: "MOP",
|
||||
3: "HKD",
|
||||
4: "USD",
|
||||
});
|
||||
//成本类型
|
||||
const cost_type = reactive({
|
||||
1: t("cost_type.unit_price"),
|
||||
2: t("cost_type.freight"),
|
||||
});
|
||||
function update_cost_type() {
|
||||
cost_type["1"] = t("cost_type.unit_price");
|
||||
cost_type["2"] = t("cost_type.freight");
|
||||
}
|
||||
|
||||
//订单状态
|
||||
const order_status = reactive({
|
||||
1: t("order_status.pending_order"),
|
||||
2: t("order_status.order_placed"),
|
||||
3: t("order_status.in_transit"),
|
||||
4: t("order_status.completed"),
|
||||
5: t("order_status.refund_requested"),
|
||||
6: t("order_status.returning"),
|
||||
7: t("order_status.refunded"),
|
||||
8: t("order_status.lost_package"),
|
||||
});
|
||||
|
||||
function update_order_status() {
|
||||
order_status["1"] = t("order_status.pending_order");
|
||||
order_status["2"] = t("order_status.order_placed");
|
||||
order_status["3"] = t("order_status.in_transit");
|
||||
order_status["4"] = t("order_status.completed");
|
||||
order_status["5"] = t("order_status.refund_requested");
|
||||
order_status["6"] = t("order_status.returning");
|
||||
order_status["7"] = t("order_status.refunded");
|
||||
order_status["8"] = t("order_status.lost_package");
|
||||
}
|
||||
|
||||
const cost_sheet_tab = reactive([]);
|
||||
// 表单对象
|
||||
const cost_sheet = reactive({
|
||||
type: '1',
|
||||
type: "1",
|
||||
int: 1,
|
||||
cost: 0.0,
|
||||
currency_type:'1'
|
||||
})
|
||||
|
||||
function add_cost(){
|
||||
var t={
|
||||
type: cost_sheet.type,
|
||||
int: cost_sheet.int,
|
||||
cost: cost_sheet.cost,
|
||||
currency_type:cost_sheet.currency_type
|
||||
}
|
||||
cost_sheet_tab.push(t)
|
||||
console.log(cost_sheet_tab)
|
||||
currency_type: "1",
|
||||
});
|
||||
|
||||
function del_cost(key) {
|
||||
cost_sheet_tab.splice(key, 1);
|
||||
}
|
||||
function add_cost() {
|
||||
cost_sheet_tab.push(JSON.parse(JSON.stringify(cost_sheet)));
|
||||
// var t = {
|
||||
// type: cost_type[cost_sheet.type],
|
||||
// int: cost_sheet.int,
|
||||
// cost: cost_sheet.cost,
|
||||
// currency_type: currency_type[cost_sheet.currency_type],
|
||||
// };
|
||||
// cost_sheet_tab.push(t);
|
||||
//console.log(t);
|
||||
}
|
||||
|
||||
// const select_beast = ref()
|
||||
// const select_type = ref()
|
||||
// function sele_init(){
|
||||
// new TomSelect(select_beast.value,{
|
||||
// create: true,
|
||||
// sortField: {
|
||||
// //field: "text",
|
||||
// //direction: "asc"
|
||||
// }
|
||||
// });
|
||||
|
||||
// new TomSelect(select_type.value,{
|
||||
// create: true,
|
||||
// sortField: {
|
||||
// //field: "text",
|
||||
// //direction: "asc"
|
||||
// }
|
||||
// });
|
||||
|
||||
// }
|
||||
|
||||
onMounted(() => {
|
||||
functionupdataTitle();
|
||||
@@ -63,6 +85,8 @@ onMounted(() => {
|
||||
// 监听语言变化,更新标题
|
||||
watch(locale, () => {
|
||||
functionupdataTitle();
|
||||
update_cost_type();
|
||||
update_order_status();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -96,7 +120,7 @@ watch(locale, () => {
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"
|
||||
>用途 <span class="form-label-description">0/100</span></label
|
||||
>备注 <span class="form-label-description">0/100</span></label
|
||||
>
|
||||
<textarea
|
||||
class="form-control"
|
||||
@@ -129,7 +153,10 @@ watch(locale, () => {
|
||||
<div class="mt-3">
|
||||
<label class="form-label">成本</label>
|
||||
|
||||
<table class="table table-vcenter card-table table-striped">
|
||||
<table
|
||||
v-show="cost_sheet_tab.length"
|
||||
class="table table-vcenter card-table table-striped"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>类型</th>
|
||||
@@ -141,14 +168,23 @@ watch(locale, () => {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="value in cost_sheet_tab">
|
||||
<td>{{value.type}}</td>
|
||||
<td class="text-secondary">{{value.int}}</td>
|
||||
<td class="text-secondary">{{value.cost}}</td>
|
||||
<td class="text-secondary">{{value.cost*value.int}}</td>
|
||||
<td class="text-secondary">{{value.currency_type}}</td>
|
||||
<tr v-for="(value, key) in cost_sheet_tab">
|
||||
<td>{{ cost_type[value.type] }}</td>
|
||||
<td class="text-secondary">{{ value.int }}</td>
|
||||
<td class="text-secondary">{{ value.cost }}</td>
|
||||
<td class="text-secondary">
|
||||
{{ value.cost * value.int }}
|
||||
</td>
|
||||
<td class="text-secondary">
|
||||
{{ currency_type[value.currency_type] }}
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-outline-danger">Del</button>
|
||||
<button
|
||||
class="btn btn-outline-danger"
|
||||
@click="del_cost(key)"
|
||||
>
|
||||
Del
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- <tr>
|
||||
@@ -174,8 +210,9 @@ watch(locale, () => {
|
||||
value="1"
|
||||
v-model="cost_sheet.type"
|
||||
>
|
||||
<option value="1">单价</option>
|
||||
<option value="2">运输</option>
|
||||
<option v-for="(value, key) in cost_type" :value="key">
|
||||
{{ value }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-xl-3">
|
||||
@@ -209,15 +246,20 @@ watch(locale, () => {
|
||||
value="1"
|
||||
v-model="cost_sheet.currency_type"
|
||||
>
|
||||
<option value="1">RMB</option>
|
||||
<option value="2">MOP</option>
|
||||
<option value="3">HKD</option>
|
||||
<option value="4">USD</option>
|
||||
<option
|
||||
v-for="(value, key) in currency_type"
|
||||
:value="key"
|
||||
>
|
||||
{{ value }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-xl-2">
|
||||
操作
|
||||
<button class="form-control btn btn-outline-primary" @click="add_cost">
|
||||
<button
|
||||
class="form-control btn btn-outline-primary"
|
||||
@click="add_cost"
|
||||
>
|
||||
添加
|
||||
</button>
|
||||
</div>
|
||||
@@ -234,7 +276,7 @@ watch(locale, () => {
|
||||
<div class="row g-5">
|
||||
<div class="col-xl-4">
|
||||
<label class="form-label required">更新时间</label>
|
||||
<datePicker></datePicker>
|
||||
<dateTimePicker></dateTimePicker>
|
||||
</div>
|
||||
<div class="col-xl-4">
|
||||
<label class="form-label">快递单号</label>
|
||||
@@ -254,13 +296,9 @@ watch(locale, () => {
|
||||
autocomplete="off"
|
||||
value="1"
|
||||
>
|
||||
<option value="1">待下单</option>
|
||||
<option value="2">已下单</option>
|
||||
<option value="3">运输中</option>
|
||||
<option value="4">已完成</option>
|
||||
<option value="5">申请退款</option>
|
||||
<option value="6">退回中</option>
|
||||
<option value="7">已退款</option>
|
||||
<option v-for="(value, key) in order_status" :value="key">
|
||||
{{ value }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
<script setup>
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
import imageCropper from '@/components/imageCropper.vue';
|
||||
|
||||
import croppertest from '@/components/croppertest.vue';
|
||||
|
||||
import imageCropperComponent from '@/components/imageCropperComponent.vue';
|
||||
|
||||
const user = useUserStore()
|
||||
|
||||
|
||||
|
||||
import useDropzone from '@/components/useDropzone.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
test
|
||||
|
||||
<imageCropper></imageCropper>
|
||||
|
||||
|
||||
<useDropzone></useDropzone>
|
||||
</template>
|
||||
@@ -1,33 +1,35 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
import { fileURLToPath, URL } from "node:url";
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
import { defineConfig } from "vite";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import vueDevTools from "vite-plugin-vue-devtools";
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
vueDevTools(),
|
||||
],
|
||||
plugins: [vue(), vueDevTools()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
||||
},
|
||||
},
|
||||
build: {
|
||||
outDir: '../../backend/dist', // 默认是 'dist',可以修改为你想要的目录名
|
||||
assetsDir: 'assets', // 静态资源目录(相对于 outDir)
|
||||
outDir: "../../backend/dist", // 默认是 'dist',可以修改为你想要的目录名
|
||||
assetsDir: "assets", // 静态资源目录(相对于 outDir)
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://127.0.0.1:8080',
|
||||
"/api": {
|
||||
target: "http://127.0.0.1:8080",
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, '/api'), // 如果需要重写路径
|
||||
rewrite: (path) => path.replace(/^\/api/, "/api"), // 如果需要重写路径
|
||||
// 如果后端接口没有 /api 前缀,可以这样写:
|
||||
// rewrite: (path) => path.replace(/^\/api/, '')
|
||||
|
||||
// 设置代理超时配置
|
||||
// proxyTimeout: 30000, // 代理服务器等待目标服务器响应的超时时间(毫秒)
|
||||
// timeout: 30000, // 整个请求的超时时间(毫秒)
|
||||
// connectTimeout: 30000, // 连接超时(毫秒,某些版本支持)
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user