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-easyinput v-model="form.name" placeholder="请输入供应商名称" :disabled="mode=='show'"/>
|
||||||
</uni-forms-item>
|
</uni-forms-item>
|
||||||
<uni-forms-item label="物料分类" required>
|
<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>
|
||||||
<uni-forms-item label="物料名称" required>
|
<uni-forms-item label="物料名称" required>
|
||||||
<uni-easyinput v-model="form.material_name" placeholder="请输入物料名称" :disabled="mode=='show'"/>
|
<uni-easyinput v-model="form.material_name" placeholder="请输入物料名称" :disabled="mode=='show'"/>
|
||||||
</uni-forms-item>
|
</uni-forms-item>
|
||||||
<uni-forms-item label="调查表" required>
|
<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>
|
||||||
<uni-forms-item label="营业执照" required>
|
<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>
|
||||||
<uni-forms-item label="质量证书" required>
|
<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-item>
|
||||||
</uni-forms>
|
</uni-forms>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="footer_fixed">
|
<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_"
|
<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>
|
: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">
|
<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_b from "../wf/ticketd_b.vue"
|
||||||
import ticketd from "../wf/ticketd.vue"
|
import ticketd from "../wf/ticketd.vue"
|
||||||
import {actStateEnum} from "@/utils/enum.js"
|
import {actStateEnum} from "@/utils/enum.js"
|
||||||
|
import xtUpload from "@/components/xtUpload.vue"
|
||||||
export default {
|
export default {
|
||||||
components: { ticketd_b, ticketd },
|
components: { ticketd_b, ticketd, xtUpload },
|
||||||
data(){
|
data(){
|
||||||
return{
|
return{
|
||||||
saveLoading: false,
|
saveLoading: false,
|
||||||
|
|
@ -88,18 +89,25 @@ import {actStateEnum} from "@/utils/enum.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
uploadSuccess(type, e){
|
handleSave(){
|
||||||
console.log('type', type, e);
|
|
||||||
console.log('form.material_type',this.form.material_type)
|
|
||||||
},
|
|
||||||
async handleSave(id){
|
|
||||||
let that = this;
|
let that = this;
|
||||||
that.$refs.customForm.validate().then(res => {
|
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 => {
|
}).catch(err => {
|
||||||
console.log('err', 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({
|
const props = defineProps({
|
||||||
workflow_key: {type: String, default: null, required: false},
|
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},
|
t_id: {type: String, default: null, required: true},
|
||||||
title: {type: String, default: null, required: false},
|
title: {type: String, default: null, required: false},
|
||||||
submit_b_func: {type: Function, 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 transitions = ref([]);
|
||||||
const currentUser = ref(uni.getStorageSync("userInfo").id);
|
const currentUser = ref(uni.getStorageSync("userInfo").id);
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
setTimeout(()=>{init()}, 1000)
|
checkPropsUntilReady()
|
||||||
// await init();
|
|
||||||
// watch(
|
|
||||||
// () => props.ticket_,
|
|
||||||
// async (newVal) => {
|
|
||||||
// if (newVal && Object.keys(newVal).length > 0) {
|
|
||||||
// await init();
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// { deep: true }
|
|
||||||
// )
|
|
||||||
})
|
})
|
||||||
|
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 suggestion = ref("")
|
||||||
const isOwn = ref(false)
|
const isOwn = ref(false)
|
||||||
const ticketId = ref(null)
|
const ticketId = ref(null)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue