还差批量图片上传
This commit is contained in:
@@ -52,6 +52,7 @@ func ApiRoot(r *gin.RouterGroup) {
|
|||||||
|
|
||||||
ApiStatic(r.Group("/static"))
|
ApiStatic(r.Group("/static"))
|
||||||
ApiUser(r.Group("/users"))
|
ApiUser(r.Group("/users"))
|
||||||
|
ApiFiles(r.Group("/files"))
|
||||||
|
|
||||||
r.GET("/", func(ctx *gin.Context) {
|
r.GET("/", func(ctx *gin.Context) {
|
||||||
ReturnJson(ctx, "apiOK", nil)
|
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",
|
"axios": "^1.13.2",
|
||||||
"bootstrap": "^5.3.8",
|
"bootstrap": "^5.3.8",
|
||||||
"cropperjs": "^2.1.0",
|
"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",
|
"litepicker": "^2.0.12",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
"tom-select": "^2.4.3",
|
"tom-select": "^2.4.3",
|
||||||
"vue": "^3.5.22",
|
"vue": "^3.5.22",
|
||||||
"vue-cropper": "^0.6.5",
|
"vue-cropper": "^0.6.5",
|
||||||
|
"vue-filepond": "^7.0.4",
|
||||||
|
"vue-flatpickr-component": "^12.0.0",
|
||||||
"vue-i18n": "^11.1.12",
|
"vue-i18n": "^11.1.12",
|
||||||
"vue-router": "^4.6.3"
|
"vue-router": "^4.6.3"
|
||||||
},
|
},
|
||||||
@@ -1883,6 +1893,12 @@
|
|||||||
"win32"
|
"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": {
|
"node_modules/@tabler/core": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tabler/core/-/core-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tabler/core/-/core-1.4.0.tgz",
|
||||||
@@ -2520,6 +2536,16 @@
|
|||||||
"node": ">=0.10"
|
"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": {
|
"node_modules/dunder-proto": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
"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": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
@@ -2698,6 +2776,12 @@
|
|||||||
"node": ">=8"
|
"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": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.11",
|
"version": "1.15.11",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||||
@@ -3011,6 +3095,12 @@
|
|||||||
"node": ">=6"
|
"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": {
|
"node_modules/kolorist": {
|
||||||
"version": "1.8.0",
|
"version": "1.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
|
||||||
@@ -4201,6 +4291,31 @@
|
|||||||
"integrity": "sha512-lSvY6IpeA/Tv/iPZ/FOkMHVRBPSlm7t57nuHEZFBMRNOH8ElvfqVlnHGDOAMlvPhh9gHiddiQoASS+fY0MFX0g==",
|
"integrity": "sha512-lSvY6IpeA/Tv/iPZ/FOkMHVRBPSlm7t57nuHEZFBMRNOH8ElvfqVlnHGDOAMlvPhh9gHiddiQoASS+fY0MFX0g==",
|
||||||
"license": "ISC"
|
"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": {
|
"node_modules/vue-i18n": {
|
||||||
"version": "11.1.12",
|
"version": "11.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.1.12.tgz",
|
||||||
|
|||||||
@@ -34,11 +34,21 @@
|
|||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"bootstrap": "^5.3.8",
|
"bootstrap": "^5.3.8",
|
||||||
"cropperjs": "^2.1.0",
|
"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",
|
"litepicker": "^2.0.12",
|
||||||
"pinia": "^3.0.4",
|
"pinia": "^3.0.4",
|
||||||
"tom-select": "^2.4.3",
|
"tom-select": "^2.4.3",
|
||||||
"vue": "^3.5.22",
|
"vue": "^3.5.22",
|
||||||
"vue-cropper": "^0.6.5",
|
"vue-cropper": "^0.6.5",
|
||||||
|
"vue-filepond": "^7.0.4",
|
||||||
|
"vue-flatpickr-component": "^12.0.0",
|
||||||
"vue-i18n": "^11.1.12",
|
"vue-i18n": "^11.1.12",
|
||||||
"vue-router": "^4.6.3"
|
"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",
|
"license": "License",
|
||||||
"source_code": "Source Code",
|
"source_code": "Source Code",
|
||||||
"copy": "Copyright © 2025 Operations. All rights reserved."
|
"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": "采购",
|
"purchase": "采购",
|
||||||
"warehouse": "仓库"
|
"warehouse": "仓库"
|
||||||
},
|
},
|
||||||
"tagadder":{
|
"tagadder": {
|
||||||
"not_fund_item":"没有找到匹配项",
|
"not_fund_item": "没有找到匹配项",
|
||||||
"loding":"正在加载...",
|
"loding": "正在加载...",
|
||||||
"add":"添加新选项: "
|
"add": "添加新选项: "
|
||||||
},
|
},
|
||||||
"cropper": {
|
"cropper": {
|
||||||
"select_image": "选择图片",
|
"select_image": "选择图片",
|
||||||
@@ -154,5 +154,19 @@
|
|||||||
"license": "协议",
|
"license": "协议",
|
||||||
"source_code": "源码",
|
"source_code": "源码",
|
||||||
"copy": "版权 © 2025 Operations. 保留所有权利。"
|
"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>
|
<script setup>
|
||||||
import { onMounted, watch, ref ,reactive} from "vue";
|
import { onMounted, watch, ref, reactive } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
import tagadder from "@/components/tagadder.vue";
|
import tagadder from "@/components/tagadder.vue";
|
||||||
import datePicker from "@/components/datePicker.vue";
|
import dateTimePicker from "@/components/dateTimePicker.vue";
|
||||||
|
|
||||||
import TomSelect from "tom-select";
|
import TomSelect from "tom-select";
|
||||||
import "tom-select/dist/css/tom-select.css";
|
import "tom-select/dist/css/tom-select.css";
|
||||||
@@ -14,47 +14,69 @@ function functionupdataTitle() {
|
|||||||
document.title = "Operations." + t("purchase.add_part");
|
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_tab = reactive([]);
|
||||||
// 表单对象
|
// 表单对象
|
||||||
const cost_sheet = reactive({
|
const cost_sheet = reactive({
|
||||||
type: '1',
|
type: "1",
|
||||||
int: 1,
|
int: 1,
|
||||||
cost: 0.0,
|
cost: 0.0,
|
||||||
currency_type:'1'
|
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)
|
|
||||||
|
|
||||||
|
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(() => {
|
onMounted(() => {
|
||||||
functionupdataTitle();
|
functionupdataTitle();
|
||||||
@@ -63,6 +85,8 @@ onMounted(() => {
|
|||||||
// 监听语言变化,更新标题
|
// 监听语言变化,更新标题
|
||||||
watch(locale, () => {
|
watch(locale, () => {
|
||||||
functionupdataTitle();
|
functionupdataTitle();
|
||||||
|
update_cost_type();
|
||||||
|
update_order_status();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -96,7 +120,7 @@ watch(locale, () => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label"
|
<label class="form-label"
|
||||||
>用途 <span class="form-label-description">0/100</span></label
|
>备注 <span class="form-label-description">0/100</span></label
|
||||||
>
|
>
|
||||||
<textarea
|
<textarea
|
||||||
class="form-control"
|
class="form-control"
|
||||||
@@ -129,7 +153,10 @@ watch(locale, () => {
|
|||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<label class="form-label">成本</label>
|
<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>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>类型</th>
|
<th>类型</th>
|
||||||
@@ -141,14 +168,23 @@ watch(locale, () => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="value in cost_sheet_tab">
|
<tr v-for="(value, key) in cost_sheet_tab">
|
||||||
<td>{{value.type}}</td>
|
<td>{{ cost_type[value.type] }}</td>
|
||||||
<td class="text-secondary">{{value.int}}</td>
|
<td class="text-secondary">{{ value.int }}</td>
|
||||||
<td class="text-secondary">{{value.cost}}</td>
|
<td class="text-secondary">{{ value.cost }}</td>
|
||||||
<td class="text-secondary">{{value.cost*value.int}}</td>
|
<td class="text-secondary">
|
||||||
<td class="text-secondary">{{value.currency_type}}</td>
|
{{ value.cost * value.int }}
|
||||||
|
</td>
|
||||||
|
<td class="text-secondary">
|
||||||
|
{{ currency_type[value.currency_type] }}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-outline-danger">Del</button>
|
<button
|
||||||
|
class="btn btn-outline-danger"
|
||||||
|
@click="del_cost(key)"
|
||||||
|
>
|
||||||
|
Del
|
||||||
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- <tr>
|
<!-- <tr>
|
||||||
@@ -174,8 +210,9 @@ watch(locale, () => {
|
|||||||
value="1"
|
value="1"
|
||||||
v-model="cost_sheet.type"
|
v-model="cost_sheet.type"
|
||||||
>
|
>
|
||||||
<option value="1">单价</option>
|
<option v-for="(value, key) in cost_type" :value="key">
|
||||||
<option value="2">运输</option>
|
{{ value }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-3">
|
<div class="col-xl-3">
|
||||||
@@ -209,15 +246,20 @@ watch(locale, () => {
|
|||||||
value="1"
|
value="1"
|
||||||
v-model="cost_sheet.currency_type"
|
v-model="cost_sheet.currency_type"
|
||||||
>
|
>
|
||||||
<option value="1">RMB</option>
|
<option
|
||||||
<option value="2">MOP</option>
|
v-for="(value, key) in currency_type"
|
||||||
<option value="3">HKD</option>
|
:value="key"
|
||||||
<option value="4">USD</option>
|
>
|
||||||
|
{{ value }}
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-2">
|
<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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -234,7 +276,7 @@ watch(locale, () => {
|
|||||||
<div class="row g-5">
|
<div class="row g-5">
|
||||||
<div class="col-xl-4">
|
<div class="col-xl-4">
|
||||||
<label class="form-label required">更新时间</label>
|
<label class="form-label required">更新时间</label>
|
||||||
<datePicker></datePicker>
|
<dateTimePicker></dateTimePicker>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-4">
|
<div class="col-xl-4">
|
||||||
<label class="form-label">快递单号</label>
|
<label class="form-label">快递单号</label>
|
||||||
@@ -254,13 +296,9 @@ watch(locale, () => {
|
|||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
value="1"
|
value="1"
|
||||||
>
|
>
|
||||||
<option value="1">待下单</option>
|
<option v-for="(value, key) in order_status" :value="key">
|
||||||
<option value="2">已下单</option>
|
{{ value }}
|
||||||
<option value="3">运输中</option>
|
</option>
|
||||||
<option value="4">已完成</option>
|
|
||||||
<option value="5">申请退款</option>
|
|
||||||
<option value="6">退回中</option>
|
|
||||||
<option value="7">已退款</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,22 +1,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useUserStore } from '@/stores/user'
|
import useDropzone from '@/components/useDropzone.vue';
|
||||||
|
|
||||||
import imageCropper from '@/components/imageCropper.vue';
|
|
||||||
|
|
||||||
import croppertest from '@/components/croppertest.vue';
|
|
||||||
|
|
||||||
import imageCropperComponent from '@/components/imageCropperComponent.vue';
|
|
||||||
|
|
||||||
const user = useUserStore()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
test
|
|
||||||
|
|
||||||
<imageCropper></imageCropper>
|
<useDropzone></useDropzone>
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@@ -1,33 +1,35 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from "node:url";
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from "vite";
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from "@vitejs/plugin-vue";
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
import vueDevTools from "vite-plugin-vue-devtools";
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [vue(), vueDevTools()],
|
||||||
vue(),
|
|
||||||
vueDevTools(),
|
|
||||||
],
|
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: '../../backend/dist', // 默认是 'dist',可以修改为你想要的目录名
|
outDir: "../../backend/dist", // 默认是 'dist',可以修改为你想要的目录名
|
||||||
assetsDir: 'assets', // 静态资源目录(相对于 outDir)
|
assetsDir: "assets", // 静态资源目录(相对于 outDir)
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
"/api": {
|
||||||
target: 'http://127.0.0.1:8080',
|
target: "http://127.0.0.1:8080",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path) => path.replace(/^\/api/, '/api'), // 如果需要重写路径
|
rewrite: (path) => path.replace(/^\/api/, "/api"), // 如果需要重写路径
|
||||||
// 如果后端接口没有 /api 前缀,可以这样写:
|
// 如果后端接口没有 /api 前缀,可以这样写:
|
||||||
// rewrite: (path) => path.replace(/^\/api/, '')
|
// rewrite: (path) => path.replace(/^\/api/, '')
|
||||||
|
|
||||||
|
// 设置代理超时配置
|
||||||
|
// proxyTimeout: 30000, // 代理服务器等待目标服务器响应的超时时间(毫秒)
|
||||||
|
// timeout: 30000, // 整个请求的超时时间(毫秒)
|
||||||
|
// connectTimeout: 30000, // 连接超时(毫秒,某些版本支持)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user