Merge branch 'main' of http://gitea.xxhhcty.xyz:8080/zcdsj/factory_mp
This commit is contained in:
commit
74e0abc0c2
|
|
@ -0,0 +1,320 @@
|
|||
<template>
|
||||
<view style="width: 100%;">
|
||||
<button @click="choseFiles" size="mini" type="primary" :disabled="disabled">选择</button>
|
||||
<view v-for="(item, index) in fileList" :key="index" style="height: 16px; margin-bottom: 12px;">
|
||||
<view style="display:flex; justify-content: space-between;">
|
||||
<view style="color:blue" @click="preview(item)">{{ item.name }}</view>
|
||||
<view style="color:red;font-weight: bold;" @click="handleRemove(index)" v-if="disabled == false">×</view>
|
||||
</view>
|
||||
<view style="height:2px"></view>
|
||||
<progress :percent="item.percent" activeColor="#4caf50" backgroundColor="#e0e0e0" stroke-width="2" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// FILE_TYPE_DOC = 10
|
||||
// FILE_TYPE_VIDEO = 20
|
||||
// FILE_TYPE_AUDIO = 30
|
||||
// FILE_TYPE_PIC = 40
|
||||
// FILE_TYPE_OTHER = 50
|
||||
import config from '@/utils/config.js'
|
||||
import { ref, onMounted, watch, defineEmits } from 'vue';
|
||||
const emit = defineEmits(["update:modelValue", "update:obj"]);
|
||||
|
||||
const props = defineProps({
|
||||
xtype: { type: String, default: "path" }, // path 或 id
|
||||
modelValue: { type: [Array, String], default: "pending" },
|
||||
obj: { type: Object, default: () => ({}) },
|
||||
accept: { type: String, default: '' },
|
||||
countMax: { type: Number, default: 1 },
|
||||
sizeMax: { type: Number, default: 1024 * 1024 * 5 },
|
||||
disabled: { type: Boolean, default: false },
|
||||
});
|
||||
|
||||
// ⚠ reactive([]) 不能整体赋值,用 ref 更合理
|
||||
const fileList = ref([])
|
||||
const disabled = ref(props.disabled)
|
||||
|
||||
// header / action
|
||||
const header = {
|
||||
Authorization: `Bearer ${uni.getStorageSync('access')}`
|
||||
}
|
||||
const action = `${config.baseUrl}/file/`
|
||||
|
||||
const inited = ref(false)
|
||||
onMounted(() => {
|
||||
checkPropsUntilReady()
|
||||
})
|
||||
|
||||
const checkPropsUntilReady = () => {
|
||||
if (inited.value) return
|
||||
|
||||
if (props.modelValue !== "pending") {
|
||||
initFileList()
|
||||
inited.value = true
|
||||
return
|
||||
}
|
||||
// ⭐ 每 200ms 查一次(非常轻量)
|
||||
setTimeout(checkPropsUntilReady, 200)
|
||||
}
|
||||
|
||||
const changeVal = () => {
|
||||
let val = null;
|
||||
if (props.xtype == "id") {
|
||||
if (props.countMax > 1){
|
||||
val= []
|
||||
fileList.value.forEach(item => {
|
||||
if(item.id){
|
||||
val.push(item.id)
|
||||
}
|
||||
})
|
||||
}else if (props.countMax == 1){
|
||||
val = null;
|
||||
if (fileList.value && fileList.value.length > 0 && fileList.value[0].id) {
|
||||
val = fileList.value[0].id
|
||||
}
|
||||
}
|
||||
}else if (props.xtype == "path"){
|
||||
if (props.countMax > 1){
|
||||
val = []
|
||||
fileList.value.forEach(item => {
|
||||
if(item.path && item.percent == 100){
|
||||
val.push(item.path)
|
||||
}
|
||||
})
|
||||
}else if (props.countMax == 1){
|
||||
val = null;
|
||||
if (fileList.value && fileList.value.length > 0 && fileList.value[0].path && fileList.value[0].percent == 100) {
|
||||
val = fileList.value[0].path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let obj = null;
|
||||
emit("update:modelValue", val)
|
||||
if (props.countMax > 1) {
|
||||
obj = fileList.value
|
||||
emit("update:obj", obj)
|
||||
}else{
|
||||
if (fileList.value && fileList.value.length > 0) {
|
||||
obj = fileList.value[0]
|
||||
emit("update:obj", obj)
|
||||
} else {
|
||||
emit("update:obj", obj)
|
||||
}
|
||||
}
|
||||
console.log(val, obj)
|
||||
}
|
||||
|
||||
const getFileType = (path) =>{
|
||||
let type = path.substring(path.lastIndexOf('.') + 1, path.length).toLowerCase()
|
||||
if (type === 'png' || type === 'jpg' || type === 'jpeg' || type === 'gif' || type === 'bmp') {
|
||||
return 40
|
||||
}
|
||||
else if (type === 'mp4' || type === 'avi' || type === 'rmvb') {
|
||||
return 20
|
||||
}
|
||||
else if (type === 'mp3' || type === 'wav' || type === 'wma') {
|
||||
return 30
|
||||
}
|
||||
return 10
|
||||
}
|
||||
/**
|
||||
* 初始化 fileList
|
||||
*/
|
||||
const initFileList = () => {
|
||||
if (props.countMax > 1) {
|
||||
let clist = []
|
||||
|
||||
// xtype = id 情况
|
||||
if (props.xtype === "id" && Array.isArray(props.obj) && props.obj.length > 0) {
|
||||
|
||||
props.obj.forEach(item => {
|
||||
clist.push({
|
||||
...item,
|
||||
url: `${config.hostUrl}${item.path}`,
|
||||
percent: 100
|
||||
})
|
||||
})
|
||||
fileList.value = clist
|
||||
}
|
||||
else if (props.xtype === "path" && props.modelValue) {
|
||||
props.modelValue.forEach(item => {
|
||||
clist.push({
|
||||
name: item.substring(item.lastIndexOf('/') + 1, item.length),
|
||||
path: item,
|
||||
url: `${config.hostUrl}${item}`,
|
||||
percent: 100,
|
||||
type: getFileType(item)
|
||||
})
|
||||
})
|
||||
fileList.value = clist
|
||||
}
|
||||
} else if (props.countMax == 1) {
|
||||
let clist = []
|
||||
if (props.xtype === "id" && props.modelValue) {
|
||||
clist.push({
|
||||
...props.obj,
|
||||
url: `${config.hostUrl}${props.obj.path}`,
|
||||
percent: 100
|
||||
})
|
||||
fileList.value = clist
|
||||
} else if (props.xtype === "path" && props.modelValue) {
|
||||
clist.push({
|
||||
name: item.substring(item.lastIndexOf('/') + 1, item.length),
|
||||
path: props.modelValue,
|
||||
url: `${config.hostUrl}${props.modelValue}`,
|
||||
percent: 100,
|
||||
type: getFileType(props.obj.path)
|
||||
})
|
||||
fileList.value = clist
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleRemove = (index) => {
|
||||
let upTask = fileList.value[index].upTask
|
||||
if (upTask) {
|
||||
upTask.abort()
|
||||
}
|
||||
fileList.value.splice(index, 1)
|
||||
changeVal()
|
||||
}
|
||||
|
||||
const preview = (item) => {
|
||||
if (item.type == 40) {
|
||||
// 获取所有类型为 40 的图片 URL
|
||||
const urls = fileList.value
|
||||
.filter(file => file.type === 40)
|
||||
.map(file => file.url)
|
||||
|
||||
// 找到当前图片的索引
|
||||
const currentIndex = urls.indexOf(item.url)
|
||||
|
||||
uni.previewImage({
|
||||
current: currentIndex >= 0 ? currentIndex : 0,
|
||||
urls: urls,
|
||||
fail: function(err) {
|
||||
console.log(err);
|
||||
uni.showToast({
|
||||
title: "预览失败",
|
||||
icon: "none"
|
||||
})
|
||||
}
|
||||
})
|
||||
} else if (item.type == 10) {
|
||||
window.open(item.url, '_blank');
|
||||
// uni.downloadFile({
|
||||
// url: item.url,
|
||||
// success: function (res) {
|
||||
// var filePath = res.tempFilePath;
|
||||
// uni.openDocument({
|
||||
// filePath: filePath,
|
||||
// showMenu: true,
|
||||
// success: function (res) {
|
||||
// console.log('打开文档成功');
|
||||
// }
|
||||
// });
|
||||
// },
|
||||
// fail: function (err) {
|
||||
// console.log("下载失败:", err)
|
||||
// uni.showToast({
|
||||
// title: "下载失败",
|
||||
// icon: "none"
|
||||
// })
|
||||
// }
|
||||
// });
|
||||
} else if (item.type == 20) {
|
||||
uni.showToast({
|
||||
title: "暂不支持预览该文件",
|
||||
icon : 'none'
|
||||
})
|
||||
} else if (item.type == 30) {
|
||||
uni.showToast({
|
||||
title: "暂不支持预览该文件",
|
||||
icon : 'none'
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "暂不支持预览该文件",
|
||||
icon : 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const choseFiles = () => {
|
||||
if (fileList.value.length >= props.countMax) {
|
||||
uni.showToast({
|
||||
title: `最多只能上传${props.countMax}个文件`,
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.chooseFile({
|
||||
count: props.countMax - fileList.value.length,
|
||||
success(res) {
|
||||
const tempFiles = res.tempFiles;
|
||||
|
||||
tempFiles.forEach(item => {
|
||||
// 文件大小校验(单位:字节)
|
||||
if (item.size > props.sizeMax * 1024 * 1024) {
|
||||
uni.showToast({
|
||||
title: `文件大小不能超过${props.sizeMax}M`,
|
||||
icon: 'none'
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建上传任务
|
||||
const upTask = uni.uploadFile({
|
||||
url: action,
|
||||
filePath: item.path,
|
||||
name: 'file',
|
||||
formData: {},
|
||||
header: header,
|
||||
success: (uploadRes) => {
|
||||
const data = JSON.parse(uploadRes.data || "{}")
|
||||
if (data) {
|
||||
fileList.value.forEach((file, index) => {
|
||||
if (file.path === item.path) {
|
||||
fileList.value[index].url = `${config.hostUrl}${data.path}`
|
||||
fileList.value[index].path = data.path
|
||||
fileList.value[index].percent = 100
|
||||
fileList.value[index].id = data.id
|
||||
fileList.value[index].upTask = null
|
||||
}
|
||||
})
|
||||
// console.log("fv", fileList.value)
|
||||
changeVal()
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log("上传失败:", err)
|
||||
}
|
||||
})
|
||||
|
||||
// 添加到列表
|
||||
fileList.value.push({
|
||||
name: item.name,
|
||||
url: null,
|
||||
path: item.path,
|
||||
percent: 0,
|
||||
type: getFileType(item.name),
|
||||
upTask: upTask
|
||||
})
|
||||
|
||||
// 🔥 关键修复:关联上传进度
|
||||
upTask.onProgressUpdate((res) => {
|
||||
fileList.value.forEach((file, index) => {
|
||||
if (file.path === item.path) {
|
||||
fileList.value[index].percent = res.progress
|
||||
}
|
||||
})
|
||||
});
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
|
@ -8,26 +8,26 @@
|
|||
<uni-easyinput v-model="form.name" placeholder="请输入供应商名称" :disabled="mode=='show'"/>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="物料分类" required>
|
||||
<uni-easyinput v-model="form.material_type" placeholder="请输入物料分类" :disabled="mode=='show'"/>
|
||||
<uni-easyinput v-model="form.material_cate" placeholder="请输入物料分类" :disabled="mode=='show'"/>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="物料名称" required>
|
||||
<uni-easyinput v-model="form.material_name" placeholder="请输入物料名称" :disabled="mode=='show'"/>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="调查表" required>
|
||||
<uni-file-picker limit="1" file-mediatype="all" v-model="form.survery_form" @success="(e)=>{uploadSuccess('1', e)}"></uni-file-picker>
|
||||
<xtUpload v-model="form.survery_form" v-model:obj="form.survery_form_" xtype="id" :disabled="mode=='show'"></xtUpload>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="营业执照" required>
|
||||
<uni-file-picker limit="1" file-mediatype="all" v-model="form.business_license" @success="uploadSuccess('2')"></uni-file-picker>
|
||||
<xtUpload v-model="form.business_license" v-model:obj="form.business_license_" xtype="id" :disabled="mode=='show'"></xtUpload>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item label="质量证书" required>
|
||||
<uni-file-picker limit="1" file-mediatype="all" v-model="form.quality_certificate" @success="uploadSuccess('3')"></uni-file-picker>
|
||||
<xtUpload v-model="form.quality_certificate" v-model:obj="form.quality_certificate_" xtype="id" :disabled="mode=='show'"></xtUpload>
|
||||
</uni-forms-item>
|
||||
</uni-forms>
|
||||
</scroll-view>
|
||||
<view class="footer_fixed">
|
||||
<button v-if="mode=='edit'" size="mini" @click="handleDel" :loading="saveLoading" :disabled="saveLoading" type="warn">
|
||||
<!-- <button v-if="mode=='edit'" size="mini" @click="handleDel" :loading="saveLoading" :disabled="saveLoading" type="warn">
|
||||
删除
|
||||
</button>
|
||||
</button> -->
|
||||
<ticketd_b v-if="form.ticket_" :t_id="form.id" :ticket_="form.ticket_"
|
||||
:ticket_data="ticket_data" @success="()=>{uni.navigateBack()}" ref="ticketd_b"></ticketd_b>
|
||||
<button v-else size="mini" @click="handleSave" :loading="saveLoading" :disabled="saveLoading" type="primary">
|
||||
|
|
@ -41,8 +41,9 @@
|
|||
import ticketd_b from "../wf/ticketd_b.vue"
|
||||
import ticketd from "../wf/ticketd.vue"
|
||||
import {actStateEnum} from "@/utils/enum.js"
|
||||
import xtUpload from "@/components/xtUpload.vue"
|
||||
export default {
|
||||
components: { ticketd_b, ticketd },
|
||||
components: { ticketd_b, ticketd, xtUpload },
|
||||
data(){
|
||||
return{
|
||||
saveLoading: false,
|
||||
|
|
@ -88,18 +89,25 @@ import {actStateEnum} from "@/utils/enum.js"
|
|||
}
|
||||
},
|
||||
methods:{
|
||||
uploadSuccess(type, e){
|
||||
console.log('type', type, e);
|
||||
console.log('form.material_type',this.form.material_type)
|
||||
},
|
||||
async handleSave(id){
|
||||
handleSave(){
|
||||
let that = this;
|
||||
that.$refs.customForm.validate().then(res => {
|
||||
that.saveLoading = true;
|
||||
that.$api.supplierauditCreate(that.form).then(res => {
|
||||
that.saveLoading = false;
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success'
|
||||
});
|
||||
uni.navigateBack()
|
||||
}).catch(e=>{
|
||||
that.saveLoading = false;
|
||||
console.log('err', err);
|
||||
})
|
||||
|
||||
}).catch(err => {
|
||||
console.log('err', err);
|
||||
})
|
||||
let res = await that.$api.supplierauditCreate(that.form)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import API from '@/utils/api';
|
|||
|
||||
const props = defineProps({
|
||||
workflow_key: {type: String, default: null, required: false},
|
||||
ticket_: {type: Object, default: null, required: false},
|
||||
ticket_: {type: [Object, String], default: "pending", required: false},
|
||||
t_id: {type: String, default: null, required: true},
|
||||
title: {type: String, default: null, required: false},
|
||||
submit_b_func: {type: Function, default: null, required: false},
|
||||
|
|
@ -26,18 +26,20 @@ const workflow = ref(null);
|
|||
const transitions = ref([]);
|
||||
const currentUser = ref(uni.getStorageSync("userInfo").id);
|
||||
onMounted(async () => {
|
||||
setTimeout(()=>{init()}, 1000)
|
||||
// await init();
|
||||
// watch(
|
||||
// () => props.ticket_,
|
||||
// async (newVal) => {
|
||||
// if (newVal && Object.keys(newVal).length > 0) {
|
||||
// await init();
|
||||
// }
|
||||
// },
|
||||
// { deep: true }
|
||||
// )
|
||||
checkPropsUntilReady()
|
||||
})
|
||||
const inited = ref(false)
|
||||
const checkPropsUntilReady = () => {
|
||||
if (inited.value) return
|
||||
|
||||
if (props.ticket_ !== "pending") {
|
||||
init()
|
||||
inited.value = true
|
||||
return
|
||||
}
|
||||
// ⭐ 每 200ms 查一次(非常轻量)
|
||||
setTimeout(checkPropsUntilReady, 200)
|
||||
}
|
||||
const suggestion = ref("")
|
||||
const isOwn = ref(false)
|
||||
const ticketId = ref(null)
|
||||
|
|
|
|||
Loading…
Reference in New Issue