文件上传组件

master
lzq 2026-01-15 17:36:36 +08:00
parent 8ba12ded82
commit 29d808402d
18 changed files with 517 additions and 276 deletions

View File

@ -1,5 +1,5 @@
<!doctype html> <!DOCTYPE html>
<html lang="zh"> <html lang="zh-CN" spellcheck="false">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>

View File

@ -4,6 +4,7 @@ import {
} from '@/common/utils/http-util.ts' } from '@/common/utils/http-util.ts'
import { saveFile } from '@/common/app' import { saveFile } from '@/common/app'
import { serverBaseUrl } from '@/common'
interface PresignedUrl extends Record<string, string | undefined> { interface PresignedUrl extends Record<string, string | undefined> {
url?: string url?: string
@ -54,10 +55,12 @@ export default {
if (filename == null || filename.length <= 0) { if (filename == null || filename.length <= 0) {
return '' return ''
} }
if (filename.startsWith('http') || filename.startsWith('https')) { if (filename.startsWith('http') || filename.startsWith('https') || filename.startsWith('blob')) {
return filename return filename
} }
if (filename.startsWith('/')) { if (filename.startsWith(serverBaseUrl + '/oss/download')) {
return filename
} else if (filename.startsWith('/')) {
return getFileUrl('/oss/download' + filename) return getFileUrl('/oss/download' + filename)
} else { } else {
return getFileUrl('/oss/download/' + filename) return getFileUrl('/oss/download/' + filename)

View File

@ -11,7 +11,7 @@ export const appName = import.meta.env.VITE_APP_NAME
/** /**
* *
*/ */
export const serverBaseUrl = import.meta.env.VITE_HTTP_SERVER_BASE_URL ?? '/' export const serverBaseUrl = import.meta.env.VITE_HTTP_SERVER_BASE_URL ?? ''
export const wsServerBaseUrl = import.meta.env.VITE_WS_SERVER_BASE_URL ?? '/' export const wsServerBaseUrl = import.meta.env.VITE_WS_SERVER_BASE_URL ?? '/'

View File

@ -202,20 +202,63 @@ function prettyDuration(date: DateTime<true | false> | Date | number | string, o
} }
} }
function endOfMonth(date?: DateTime<true | false>) { function beginOfDay(date?: DateTime<true | false>) {
if (date == null) { if (date == null) {
return date = now() date = now()
} }
return date.endOf('month') return date.startOf('day')
}
function endOfDay(date?: DateTime<true | false>) {
if (date == null) {
date = now()
}
return date.endOf('day')
} }
function beginOfMonth(date?: DateTime<true | false>) { function beginOfMonth(date?: DateTime<true | false>) {
if (date == null) { if (date == null) {
return date = now() date = now()
} }
return date.startOf('month') return date.startOf('month')
} }
function endOfMonth(date?: DateTime<true | false>) {
if (date == null) {
date = now()
}
return date.endOf('month')
}
function beginOfWeek(date?: DateTime<true | false>) {
if (date == null) {
date = now()
}
return date.startOf('week')
}
function endOfWeek(date?: DateTime<true | false>) {
if (date == null) {
date = now()
}
return date.endOf('week')
}
function beginOfYear(date?: DateTime<true | false>) {
if (date == null) {
date = now()
}
return date.startOf('year')
}
function endOfYear(date?: DateTime<true | false>) {
if (date == null) {
date = now()
}
return date.endOf('year')
}
function toDate(date: DateTime<true | false>) { function toDate(date: DateTime<true | false>) {
return date.toJSDate() return date.toJSDate()
} }
@ -228,6 +271,12 @@ export default {
FMT, FMT,
endOfMonth, endOfMonth,
beginOfMonth, beginOfMonth,
beginOfDay,
endOfDay,
beginOfWeek,
endOfWeek,
beginOfYear,
endOfYear,
toDate, toDate,
prettyDuration, prettyDuration,
} }

View File

@ -99,7 +99,7 @@ const searchForm = Utils.resetAble(reactive<F>({
const tableData = Utils.resetAble(reactive<TT[]>([])) as ResetAble<TT[]> const tableData = Utils.resetAble(reactive<TT[]>([])) as ResetAble<TT[]>
const totalCount = ref(0) const totalCount = ref(0)
const loading = ref<boolean>(false) const loading = ref<boolean>(false)
const showSearchForm = ref<boolean>(true) const showSearchForm = ref<boolean>(false)
function doReset() { function doReset() {
searchForm.$reset() searchForm.$reset()
@ -182,7 +182,18 @@ onMounted(doSearch)
<button style="display: none" type="submit"></button> <button style="display: none" type="submit"></button>
</ElForm> </ElForm>
<ElTooltip content="刷新" placement="top"> <ElTooltip content="刷新" placement="top">
<ElButton :icon="elIcons.Refresh" :loading="loading" type="default" @click="doSearch"/> <ElDropdown split-button @click="doSearch" @command="(command)=>{
if(command === 'reset'){
doReset()
}
}">
<ElButton :icon="elIcons.Refresh" :loading="loading" type="default"/>
<template #dropdown>
<ElDropdownMenu slot="dropdown">
<ElDropdownItem command="reset">重置并刷新</ElDropdownItem>
</ElDropdownMenu>
</template>
</ElDropdown>
</ElTooltip> </ElTooltip>
<template v-if="!Colls.isEmpty(rightTools)"> <template v-if="!Colls.isEmpty(rightTools)">
<ElButton v-for="(tool,i) in rightTools" :key="'tool-bar-right-'+i" <ElButton v-for="(tool,i) in rightTools" :key="'tool-bar-right-'+i"
@ -405,15 +416,27 @@ onMounted(doSearch)
//box-shadow: rgba(0, 0, 0, 0.12) 0px 0px 12px 0px; //box-shadow: rgba(0, 0, 0, 0.12) 0px 0px 12px 0px;
//padding 10px //padding 10px
:deep(.el-form) { .tool-bar-left {
.el-form-item { flex 1
margin: 0;
}
} }
& > div:last-child { .tool-bar-right {
flex 1
display flex display flex
gap 10px gap 10px
justify-content end
:deep(.el-form) {
display flex
gap 10px
.el-form-item {
margin: 0;
flex 1
}
}
:deep(.el-button--default) { :deep(.el-button--default) {
width 32px width 32px

View File

@ -9,22 +9,31 @@ import { serverBaseUrl } from '@/common'
import { type R } from '@/common/utils/http-util.ts' import { type R } from '@/common/utils/http-util.ts'
import Strings from '@/common/utils/strings.ts' import Strings from '@/common/utils/strings.ts'
import AppApi from '@/common/app/app-api.ts' import AppApi from '@/common/app/app-api.ts'
import type { UploadProps } from 'element-plus/es/components/upload/src/upload'
const props = defineProps<{ const props = withDefaults(defineProps<{
files?: string[] files?: string[]
file?: string file?: string
limit: number limit?: number
}>() uploadProps?: Partial<Omit<UploadProps, 'httpRequest' | 'crossorigin' | 'multiple'
| 'data' | 'action' | 'headers' | 'limit' | 'onError'
| 'onRemove' | 'onSuccess' | 'onPreview' | 'fileList' | 'beforeUpload' | 'beforeRemove' | 'onChange' | 'onProgress' | 'name'>>
}>(), {
limit: 1,
// @ts-ignore
uploadProps: {},
})
const multiple = computed(() => props.limit > 1)
const emit = defineEmits([ 'update:files', 'update:file' ]) const emit = defineEmits([ 'update:files', 'update:file' ])
const appUserStore = useAppUserStore() const appUserStore = useAppUserStore()
const showPreview = ref(false)
const headers = computed(() => ({ const headers = computed(() => ({
Authorization: appUserStore.token!, Authorization: appUserStore.token!,
})) }))
const uploadUrl = serverBaseUrl + '/oss/upload' const uploadUrl = serverBaseUrl + '/oss/upload'
const files = ref<UploadUserFile[]>([]) const filesList = ref<UploadUserFile[]>([])
function uploadSuccHandler(response: R<string>, _: UploadFile, uploadFiles: UploadFiles) { function uploadSuccHandler(response: R<string>, _: UploadFile, uploadFiles: UploadFiles) {
if (props.limit === 1) { if (props.limit === 1) {
@ -38,7 +47,7 @@ function uploadSuccHandler(response: R<string>, _: UploadFile, uploadFiles: Uplo
function rmFileHandler(_: UploadFile, uploadFiles: UploadFiles) { function rmFileHandler(_: UploadFile, uploadFiles: UploadFiles) {
if (props.limit === 1) { if (props.limit === 1) {
if (uploadFiles.length > 0) { if (uploadFiles.length > 0) {
emit('update:file', (files.value[0].response as R<string>).data) emit('update:file', (filesList.value[0].response as R<string>).data)
} else { } else {
emit('update:file', undefined) emit('update:file', undefined)
} }
@ -52,6 +61,11 @@ function uploadFailHandler(response: any, uploadFile: UploadFile, uploadFiles: U
console.log(response, uploadFile, uploadFiles) console.log(response, uploadFile, uploadFiles)
} }
const previewList = computed(() => filesList.value.map(it => AppApi.fileUrl(it.url)))
const handlePictureCardPreview = () => {
console.log(previewList.value, filesList.value)
showPreview.value = true
}
defineExpose({ defineExpose({
setDefaultFiles(urls: string[]) { setDefaultFiles(urls: string[]) {
if (urls.length > 0) { if (urls.length > 0) {
@ -60,7 +74,7 @@ defineExpose({
if (Strings.isBlank(url)) { if (Strings.isBlank(url)) {
continue continue
} }
files.value?.push({ filesList.value?.push({
uid: i, uid: i,
name: url.substring(url.lastIndexOf('/') + 1), name: url.substring(url.lastIndexOf('/') + 1),
url: AppApi.fileUrl(url), url: AppApi.fileUrl(url),
@ -76,18 +90,53 @@ defineExpose({
<template> <template>
<ElUpload <ElUpload
v-model:file-list="files" v-model:file-list="filesList"
:action="uploadUrl" :action="uploadUrl"
:headers="headers" :headers="headers"
:limit="limit" :limit="limit"
:multiple="multiple"
:on-error="uploadFailHandler" :on-error="uploadFailHandler"
:on-remove="rmFileHandler" :on-remove="rmFileHandler"
:on-success="uploadSuccHandler" :on-success="uploadSuccHandler"
v-bind="$attrs"> :on-preview="handlePictureCardPreview"
<slot/> class="a-uploader"
v-bind="uploadProps">
<slot>
<ElIcon class="default-icon">
<ElIconPlus/>
</ElIcon>
</slot>
<template #tip>
<slot name="tip"/>
</template>
</ElUpload> </ElUpload>
<ElImageViewer
v-if="showPreview"
:url-list="previewList"
show-progress
style="position: absolute"
@close="showPreview = false"
/>
</template> </template>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.a-uploader {
:deep(.el-upload) {
background-color white
}
:deep(.el-upload-dragger) {
height: 100%;
width: 100%;
border: none;
display: flex;
justify-content: center;
align-items: center;
}
.default-icon {
color: var(--el-text-color-secondary);
font-size: 28px;
}
}
</style> </style>

View File

@ -5,7 +5,6 @@
// ------ // ------
// Generated by unplugin-vue-components // Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399 // Read more: https://github.com/vuejs/core/pull/3399
import { GlobalComponents } from 'vue'
export {} export {}
@ -33,8 +32,12 @@ declare module 'vue' {
ElHeader: typeof import('element-plus/es')['ElHeader'] ElHeader: typeof import('element-plus/es')['ElHeader']
ElIcon: typeof import('element-plus/es')['ElIcon'] ElIcon: typeof import('element-plus/es')['ElIcon']
ElIconCircleClose: typeof import('@element-plus/icons-vue')['CircleClose'] ElIconCircleClose: typeof import('@element-plus/icons-vue')['CircleClose']
ElIconCirclePlus: typeof import('@element-plus/icons-vue')['CirclePlus']
ElIconDelete: typeof import('@element-plus/icons-vue')['Delete']
ElIconPicture: typeof import('@element-plus/icons-vue')['Picture'] ElIconPicture: typeof import('@element-plus/icons-vue')['Picture']
ElIconPlus: typeof import('@element-plus/icons-vue')['Plus']
ElImage: typeof import('element-plus/es')['ElImage'] ElImage: typeof import('element-plus/es')['ElImage']
ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMain: typeof import('element-plus/es')['ElMain'] ElMain: typeof import('element-plus/es')['ElMain']
@ -87,8 +90,12 @@ declare global {
const ElHeader: typeof import('element-plus/es')['ElHeader'] const ElHeader: typeof import('element-plus/es')['ElHeader']
const ElIcon: typeof import('element-plus/es')['ElIcon'] const ElIcon: typeof import('element-plus/es')['ElIcon']
const ElIconCircleClose: typeof import('@element-plus/icons-vue')['CircleClose'] const ElIconCircleClose: typeof import('@element-plus/icons-vue')['CircleClose']
const ElIconCirclePlus: typeof import('@element-plus/icons-vue')['CirclePlus']
const ElIconDelete: typeof import('@element-plus/icons-vue')['Delete']
const ElIconPicture: typeof import('@element-plus/icons-vue')['Picture'] const ElIconPicture: typeof import('@element-plus/icons-vue')['Picture']
const ElIconPlus: typeof import('@element-plus/icons-vue')['Plus']
const ElImage: typeof import('element-plus/es')['ElImage'] const ElImage: typeof import('element-plus/es')['ElImage']
const ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
const ElInput: typeof import('element-plus/es')['ElInput'] const ElInput: typeof import('element-plus/es')['ElInput']
const ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] const ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
const ElMain: typeof import('element-plus/es')['ElMain'] const ElMain: typeof import('element-plus/es')['ElMain']

View File

@ -91,11 +91,10 @@ defineExpose({
<ElFormItem prop="avatar"> <ElFormItem prop="avatar">
<Uploader <Uploader
v-model:file="userInfoForm.avatar" v-model:file="userInfoForm.avatar"
:limit="1" :upload-props="{
:multiple="true" accept: 'image/*',
accept="image/*" listType:'picture'
class="avatar-uploader" }">
list-type="picture">
<ElButton>点击上传头像</ElButton> <ElButton>点击上传头像</ElButton>
</Uploader> </Uploader>
</ElFormItem> </ElFormItem>
@ -116,10 +115,11 @@ defineExpose({
} }
} }
.avatar-uploader {
:deep(.a-uploader) {
width 100%; width 100%;
:deep(.el-upload) { .el-upload {
width 100%; width 100%;
& > button { & > button {

View File

@ -5,25 +5,46 @@
:left-tools="leftTools" :left-tools="leftTools"
:paging="paging"> :paging="paging">
<template #searchFormItem="{ searchForm }"> <template #searchFormItem="{ searchForm }">
<ElFormItem label="业务类型">
<ElSelect v-model="searchForm.bizType" clearable placeholder="业务类型" @change="research">
<ElOption v-for="item in bizList" :key="item.value" :label="item.label" :value="item.value"/>
</ElSelect>
</ElFormItem>
<ElFormItem label="分类名称"> <ElFormItem label="分类名称">
<ElInput v-model="searchForm.categoryName" placeholder="分类名称"/> <ElInput v-model="searchForm.categoryName" clearable placeholder="分类名称" @clear="research"/>
</ElFormItem>
<ElFormItem label="创建时间">
<ElDatePicker
v-model="searchForm.createTimes"
:default-time="createTimeDefaultTime"
:shortcuts="shortcuts"
clearable
end-placeholder="结束时间"
start-placeholder="开始时间"
type="datetimerange"
@change="research"
/>
</ElFormItem> </ElFormItem>
</template> </template>
<template #simpleSearchFormItem="{ searchForm }"> <template #simpleSearchFormItem="{ searchForm }">
<ElFormItem style="min-width: 200px">
<ElSelect v-model="searchForm.bizType" clearable placeholder="业务类型" @change="research">
<ElOption v-for="item in bizList" :key="item.value" :label="item.label" :value="item.value"/>
</ElSelect>
</ElFormItem>
<ElFormItem> <ElFormItem>
<ElInput v-model="searchForm.categoryName" clearable placeholder="分类名称" @clear="research"/> <ElInput v-model="searchForm.categoryName" clearable placeholder="分类名称" @clear="research"/>
</ElFormItem> </ElFormItem>
</template> </template>
<template #columns> <template #columns>
<ElTableColumn label="业务类型" prop="bizTypeName"/>
<ElTableColumn label="分类名称" prop="categoryName"/>
<ElTableColumn label="图片" prop="picture"> <ElTableColumn label="图片" prop="picture">
<template #default="{ row }"> <template #default="{ row }">
<el-image :preview-src-list="[AppApi.fileUrl(row.picture)]" :src="AppApi.fileUrl(row.picture)" preview-teleported show-progress style="width: 60px; height: 60px"/> <el-image :preview-src-list="[AppApi.fileUrl(row.picture)]" :src="AppApi.fileUrl(row.picture)" preview-teleported show-progress style="width: 32px; height: 32px"/>
</template> </template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn label="业务类型" prop="bizTypeTxt"/>
<ElTableColumn label="分类名称" prop="categoryName"/>
<ElTableColumn label="创建时间" prop="createTime"/> <ElTableColumn label="创建时间" prop="createTime"/>
<ElTableColumn label="修改时间" prop="modifyTime"/>
</template> </template>
<GoodsCategoryForm ref="goodsCategoryForm" @edit-succ="research"/> <GoodsCategoryForm ref="goodsCategoryForm" @edit-succ="research"/>
</FormPage> </FormPage>
@ -38,9 +59,60 @@ import FormPage, {
type ActionColumnType, type ActionColumnType,
type ToolType, type ToolType,
} from '@/components/page/FormPage.vue' } from '@/components/page/FormPage.vue'
import Times from '@/common/utils/times.ts'
const goodsCategoryFormIns = useTemplateRef<InstanceType<typeof GoodsCategoryForm>>('goodsCategoryForm') const goodsCategoryFormIns = useTemplateRef<InstanceType<typeof GoodsCategoryForm>>('goodsCategoryForm')
const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage') const formPageIns = useTemplateRef<ComponentExposed<typeof FormPage>>('formPage')
const createTimeDefaultTime: [ Date, Date ] = [
Times.toDate(Times.beginOfDay()),
Times.toDate(Times.endOfDay()),
]
const bizList = [
{
value: 'ZaiShengPin',
label: '再生品',
},
{
value: 'HuiShouPin',
label: '回收品',
},
{
value: 'QiTa',
label: '其他',
},
]
const shortcuts = [
{
text: '今天',
value: () => [ Times.toDate(Times.beginOfDay()), Times.toDate(Times.endOfDay()) ],
},
{
text: '昨天',
value: () => {
const time = Times.now().minus({day: 1})
return [ Times.toDate(Times.beginOfDay(time)), Times.toDate(Times.endOfDay(time)) ]
},
},
{
text: '本周',
value: () => {
return [ Times.toDate(Times.beginOfWeek()), Times.toDate(Times.endOfWeek()) ]
},
},
{
text: '本月',
value: () => {
return [ Times.toDate(Times.beginOfMonth()), Times.toDate(Times.endOfMonth()) ]
},
},
{
text: '今年',
value: () => {
return [ Times.toDate(Times.beginOfYear()), Times.toDate(Times.endOfYear()) ]
},
},
]
const leftTools: ToolType[] = [ const leftTools: ToolType[] = [
{ {
icon: 'Plus', icon: 'Plus',
@ -83,6 +155,11 @@ function research() {
} }
function paging(param: GoodsCategoryTypes.SearchGoodsCategoryParam) { function paging(param: GoodsCategoryTypes.SearchGoodsCategoryParam) {
return GoodsCategoryApi.paging(param) return GoodsCategoryApi.paging({
bizType: param.bizType,
categoryName: param.categoryName,
createTimeStart: param.createTimes?.[0] ? Times.format(param.createTimes[0]) : undefined,
createTimeEnd: param.createTimes?.[1] ? Times.format(param.createTimes[1]) : undefined,
})
} }
</script> </script>

View File

@ -6,124 +6,128 @@
<!-- biz_typeZaiShengPin-再生品HuiShouPin-回收品QiTa其他" --> <!-- biz_typeZaiShengPin-再生品HuiShouPin-回收品QiTa其他" -->
<el-select v-model="formData.bizType" :disabled="status === 'view'" placeholder="业务类型" style="width: 240px"> <el-select v-model="formData.bizType" :disabled="status === 'view'" placeholder="业务类型" style="width: 240px">
<el-option v-for="item in bizList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in bizList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="分类名称" prop="categoryName"> <ElFormItem label-width="90" label="分类名称" prop="categoryName">
<ElInput v-model="formData.categoryName" :disabled="status === 'view'" placeholder="分类名称" /> <ElInput v-model="formData.categoryName" :disabled="status === 'view'" placeholder="分类名称"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="图片" prop="picture"> <ElFormItem label-width="90" label="图片" prop="picture">
<!-- <ElInput <Uploader
v-model="formData.picture" ref="uploader"
:disabled="status === 'view'" v-model:file="formData.picture"
placeholder="图片"/> --> :upload-props="{
<Uploader v-model:file="formData.picture" :limit="1" :multiple="true" accept="image/*" class="avatar-uploader" list-type="picture-card"> accept: 'image/*',
<span style="font-size: 50px; padding: 0 40px">+</span> listType:'picture-card',
drag:false
<!-- <ElButton>点击上传图片</ElButton> --> }"/>
</Uploader>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="排序" prop="sort"> <ElFormItem label-width="90" label="排序" prop="sort">
<ElInput v-model="formData.sort" :disabled="status === 'view'" placeholder="排序" /> <ElInput v-model="formData.sort" :disabled="status === 'view'" placeholder="排序"/>
</ElFormItem> </ElFormItem>
</ElForm> </ElForm>
<template #footer> <template #footer>
<ElButton @click="showDialog = false">{{ status === "view" ? "关闭" : "取消" }}</ElButton> <ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton> <ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton>
</template> </template>
</ElDialog> </ElDialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import GoodsCategoryApi from "@/pages/gds/goods-category/goods-category-api.ts"; import GoodsCategoryApi from '@/pages/gds/goods-category/goods-category-api.ts'
import Strings from "@/common/utils/strings.ts"; import Strings from '@/common/utils/strings.ts'
import FormUtil from "@/common/utils/formUtil.ts"; import FormUtil from '@/common/utils/formUtil.ts'
import Uploader from "@/components/uploader/Uploader.vue"; import Uploader from '@/components/uploader/Uploader.vue'
import Utils from "@/common/utils"; import Utils from '@/common/utils'
import { ElMessage, type FormInstance, type FormRules } from "element-plus"; import {
ElMessage,
type FormInstance,
type FormRules,
} from 'element-plus'
const emits = defineEmits(["editSucc"]); const emits = defineEmits([ 'editSucc' ])
const showDialog = ref(false); const showDialog = ref(false)
const submiting = ref(false); const submiting = ref(false)
const status = ref<"add" | "view" | "modify">("add"); const status = ref<'add' | 'view' | 'modify'>('add')
const goodsCategoryFormIns = useTemplateRef<FormInstance>("goodsCategoryForm"); const goodsCategoryFormIns = useTemplateRef<FormInstance>('goodsCategoryForm')
const uploaderIns = useTemplateRef<InstanceType<typeof Uploader>>('uploader')
const bizList = [ const bizList = [
{ {
value: "ZaiShengPin", value: 'ZaiShengPin',
label: "再生品", label: '再生品',
}, },
{ {
value: "HuiShouPin", value: 'HuiShouPin',
label: "回收品", label: '回收品',
}, },
{ {
value: "QiTa", value: 'QiTa',
label: "其他", label: '其他',
}, },
]; ]
const formData = Utils.resetAble(reactive<any>({})); const formData = Utils.resetAble(reactive<any>({}))
const rules = reactive<FormRules<GoodsCategoryTypes.SearchGoodsCategoryResult>>({ const rules = reactive<FormRules<GoodsCategoryTypes.SearchGoodsCategoryResult>>({
id: [{ required: true, message: "请填写Id", trigger: "blur" }], bizType: [ {required: true, message: '请填写业务类型', trigger: 'blur'} ],
bizType: [{ required: true, message: "请填写业务类型", trigger: "blur" }], categoryName: [ {required: true, message: '请填写分类名称', trigger: 'blur'} ],
categoryName: [{ required: true, message: "请填写分类名称", trigger: "blur" }], picture: [ {required: true, message: '请填写图片', trigger: 'blur'} ],
picture: [{ required: true, message: "请填写图片", trigger: "blur" }], sort: [ {required: true, message: '请填写排序', trigger: 'blur'} ],
sort: [{ required: true, message: "请填写排序", trigger: "blur" }], creatorId: [ {required: true, message: '请填写创建人 Idsys_user.id', trigger: 'blur'} ],
creatorId: [{ required: true, message: "请填写创建人 Idsys_user.id", trigger: "blur" }], modifierId: [ {required: true, message: '请填写修改人 Idsys_user.id', trigger: 'blur'} ],
modifierId: [{ required: true, message: "请填写修改人 Idsys_user.id", trigger: "blur" }], createTime: [ {required: true, message: '请填写创建时间', trigger: 'blur'} ],
createTime: [{ required: true, message: "请填写创建时间", trigger: "blur" }], modifyTime: [ {required: true, message: '请填写修改时间', trigger: 'blur'} ],
modifyTime: [{ required: true, message: "请填写修改时间", trigger: "blur" }], deleted: [ {required: true, message: '请填写是否删除; 0-->未删除、1-->已删除', trigger: 'blur'} ],
deleted: [{ required: true, message: "请填写是否删除; 0-->未删除、1-->已删除", trigger: "blur" }], })
});
function dialogCloseHandler() { function dialogCloseHandler() {
formData.$reset(); formData.$reset()
} }
function submitHandler() { function submitHandler() {
if (status.value === "view") return; if (status.value === 'view') return
submiting.value = true; submiting.value = true
if (formData.id != null) { if (formData.id != null) {
FormUtil.submit(goodsCategoryFormIns, () => GoodsCategoryApi.modify(formData)) FormUtil.submit(goodsCategoryFormIns, () => GoodsCategoryApi.modify(formData))
.then(() => { .then(() => {
ElMessage.success("修改成功"); ElMessage.success('修改成功')
emits("editSucc"); emits('editSucc')
showDialog.value = false; showDialog.value = false
}) })
.finally(() => { .finally(() => {
submiting.value = false; submiting.value = false
}); })
} else { } else {
FormUtil.submit(goodsCategoryFormIns, () => GoodsCategoryApi.add(formData)) FormUtil.submit(goodsCategoryFormIns, () => GoodsCategoryApi.add(formData))
.then(() => { .then(() => {
ElMessage.success("添加成功"); ElMessage.success('添加成功')
emits("editSucc"); emits('editSucc')
showDialog.value = false; showDialog.value = false
}) })
.finally(() => { .finally(() => {
submiting.value = false; submiting.value = false
}); })
} }
} }
defineExpose({ defineExpose({
open(data: any = {}) { open(data: any = {}) {
showDialog.value = true; showDialog.value = true
if (!Strings.isBlank(data.id)) { if (!Strings.isBlank(data.id)) {
status.value = "modify"; status.value = 'modify'
GoodsCategoryApi.detail(data.id!).then((res) => { GoodsCategoryApi.detail(data.id!).then((res) => {
formData.$reset(res.data); formData.$reset(res.data)
}); if (res.data.picture != null) uploaderIns.value?.setDefaultFiles([ res.data.picture ])
})
} else { } else {
status.value = "add"; status.value = 'add'
formData.$reset(data); formData.$reset(data)
} }
}, },
}); })
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>

View File

@ -3,26 +3,16 @@ export {}
declare global { declare global {
namespace GoodsCategoryTypes { namespace GoodsCategoryTypes {
interface SearchGoodsCategoryParam extends G.PageParam { interface SearchGoodsCategoryParam extends G.PageParam {
// Id
id?: string
// 业务类型字典代码biz_typeZaiShengPin-->再生品、HuiShouPin-->回收品、QiTa-->其他 // 业务类型字典代码biz_typeZaiShengPin-->再生品、HuiShouPin-->回收品、QiTa-->其他
bizType?: string bizType?: string
// 分类名称 // 分类名称
categoryName?: string categoryName?: string
// 图片 // 创建时间范围
picture?: string createTimes?: [ Date, Date ]
// 排序
sort?: number
// 创建人 Idsys_user.id
creatorId?: string
// 修改人 Idsys_user.id
modifierId?: string
// 创建时间
createTime?: string
// 修改时间 // 修改时间
modifyTime?: string createTimeStart?: string
// 是否删除; 0-->未删除、1-->已删除 // 是否删除; 0-->未删除、1-->已删除
deleted?: boolean createTimeEnd?: string
} }
interface SearchGoodsCategoryResult { interface SearchGoodsCategoryResult {

View File

@ -29,21 +29,21 @@
</template> </template>
<template #columns> <template #columns>
<ElTableColumn label="商品编码" prop="sn"/> <ElTableColumn label="商品编码" prop="sn"/>
<ElTableColumn label="产品名称" prop="goodsName"/>
<ElTableColumn label="规格" prop="specParams"/>
<ElTableColumn label="图片" width="100"> <ElTableColumn label="图片" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-image :preview-src-list="[AppApi.fileUrl(row.picture)]" :src="AppApi.fileUrl(row.picture)" preview-teleported show-progress style="width: 60px; height: 60px"/> <el-image :preview-src-list="[AppApi.fileUrl(row.picture)]" :src="AppApi.fileUrl(row.picture)" preview-teleported show-progress style="width: 32px; height: 32px"/>
</template> </template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn label="产品名称" prop="goodsName"/>
<ElTableColumn label="规格" prop="specParams"/>
<ElTableColumn label="是否可用" prop="canuse"> <ElTableColumn label="是否可用" prop="canuse">
<template #default="{ row }"> <template #default="{row}">
{{ row.canuse ? '是' : '否' }} <ElSwitch v-model="row.canuse" @change="enableGoodsHandler($event,row.id)"/>
</template> </template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn label="备注" prop="memo"/> <ElTableColumn label="备注" prop="memo"/>
<ElTableColumn label="创建时间" prop="createTime" width="160"/> <ElTableColumn label="创建时间" prop="createTime" width="160"/>
<ElTableColumn label="修改时间" prop="modifyTime" width="160"/>
</template> </template>
<GoodsForm ref="goodsForm" @edit-succ="editSuccHandler"/> <GoodsForm ref="goodsForm" @edit-succ="editSuccHandler"/>
</FormPage> </FormPage>
@ -106,4 +106,12 @@ const leftTools: ToolType[] = [
function paging(param: GoodsTypes.SearchGoodsParam) { function paging(param: GoodsTypes.SearchGoodsParam) {
return GoodsApi.paging(param) return GoodsApi.paging(param)
} }
function enableGoodsHandler(enable: boolean, id: string) {
GoodsApi.enable({enable, id})
.then(() => {
ElMessage.success(enable ? '启用成功' : '禁用成功')
editSuccHandler()
})
}
</script> </script>

View File

@ -4,38 +4,42 @@
<ElFormItem label-width="90" label="产品类型" prop="goodsCategoryId"> <ElFormItem label-width="90" label="产品类型" prop="goodsCategoryId">
<!-- <ElInput v-model="formData.goodsCategoryId" :disabled="status === 'view'" placeholder="产品类型 Id" /> --> <!-- <ElInput v-model="formData.goodsCategoryId" :disabled="status === 'view'" placeholder="产品类型 Id" /> -->
<el-select v-model="formData.goodsCategoryId" :disabled="status === 'view'" placeholder="产品类型" filterable remote reserve-keyword remote-show-suffix :remote-method="remoteMethod" :loading="loading" style="width: 240px"> <el-select v-model="formData.goodsCategoryId" :disabled="status === 'view'" placeholder="产品类型" filterable remote reserve-keyword remote-show-suffix :remote-method="remoteMethod" :loading="loading" style="width: 240px">
<el-option v-for="item in category" :key="item.id" :label="item.categoryName" :value="item.id" /> <el-option v-for="item in category" :key="item.id" :label="item.categoryName" :value="item.id"/>
</el-select> </el-select>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="商品编码" prop="sn"> <ElFormItem label-width="90" label="商品编码" prop="sn">
<ElInput v-model="formData.sn" :disabled="status === 'view'" placeholder="商品编码" /> <ElInput v-model="formData.sn" :disabled="status === 'view'" placeholder="商品编码"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="产品名称" prop="goodsName"> <ElFormItem label-width="90" label="产品名称" prop="goodsName">
<ElInput v-model="formData.goodsName" :disabled="status === 'view'" placeholder="产品名称" /> <ElInput v-model="formData.goodsName" :disabled="status === 'view'" placeholder="产品名称"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="规格" prop="specParams"> <ElFormItem label-width="90" label="规格" prop="specParams">
<ElInput v-model="formData.specParams" :disabled="status === 'view'" placeholder="规格" /> <ElInput v-model="formData.specParams" :disabled="status === 'view'" placeholder="规格"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="图片" prop="picture"> <ElFormItem label-width="90" label="图片" prop="picture">
<Uploader v-model:file="formData.picture" :limit="1" :multiple="true" accept="image/*" class="avatar-uploader" list-type="picture-card"> <Uploader
<span style="font-size: 50px; padding: 0 40px">+</span> ref="uploader"
</Uploader> v-model:file="formData.picture"
:upload-props="{
accept: 'image/*',
listType:'picture-card'
}"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="计量单位" prop="unit"> <ElFormItem label-width="90" label="计量单位" prop="unit">
<ADict v-model="formData.unit" :disabled="status === 'view'" dict-key="unit" placeholder="计量单位" style="width: 240px"/> <ADict v-model="formData.unit" :disabled="status === 'view'" dict-key="unit" placeholder="计量单位" style="width: 240px"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="排序" prop="sort"> <ElFormItem label-width="90" label="排序" prop="sort">
<ElInput v-model="formData.sort" :disabled="status === 'view'" placeholder="请输入排序" /> <ElInput v-model="formData.sort" :disabled="status === 'view'" placeholder="请输入排序"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="备注" prop="memo"> <ElFormItem label-width="90" label="备注" prop="memo">
<ElInput v-model="formData.memo" :disabled="status === 'view'" placeholder="请输入备注" /> <ElInput v-model="formData.memo" :disabled="status === 'view'" placeholder="请输入备注"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="是否可用" prop="canuse"> <ElFormItem label-width="90" label="是否可用" prop="canuse">
<el-switch v-model="formData.canuse" :disabled="status === 'view'" /> <el-switch v-model="formData.canuse" :disabled="status === 'view'"/>
</ElFormItem> </ElFormItem>
</ElForm> </ElForm>
<template #footer> <template #footer>
<ElButton @click="showDialog = false">{{ status === "view" ? "关闭" : "取消" }}</ElButton> <ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton> <ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton>
</template> </template>
</ElDialog> </ElDialog>
@ -56,97 +60,99 @@ import GoodsCategoryApi from '@/pages/gds/goods-category/goods-category-api.ts'
import DictApi from '@/pages/sys/dict/dict-api.ts' import DictApi from '@/pages/sys/dict/dict-api.ts'
import ADict from '@/components/a-dict/ADict.vue' import ADict from '@/components/a-dict/ADict.vue'
const emits = defineEmits(["editSucc"]); const emits = defineEmits([ 'editSucc' ])
const showDialog = ref(false); const showDialog = ref(false)
const submiting = ref(false); const submiting = ref(false)
const status = ref<"add" | "view" | "modify">("add"); const status = ref<'add' | 'view' | 'modify'>('add')
const goodsFormIns = useTemplateRef<FormInstance>("goodsForm"); const goodsFormIns = useTemplateRef<FormInstance>('goodsForm')
const uploaderIns = useTemplateRef<InstanceType<typeof Uploader>>('uploader')
const formData = Utils.resetAble(reactive<GoodsTypes.SearchGoodsResult>({ canuse: true })); const formData = Utils.resetAble(reactive<GoodsTypes.SearchGoodsResult>({canuse: true}))
const rules = reactive<FormRules<GoodsTypes.SearchGoodsResult>>({ const rules = reactive<FormRules<GoodsTypes.SearchGoodsResult>>({
id: [{ required: true, message: "请填写Id", trigger: "blur" }], id: [ {required: true, message: '请填写Id', trigger: 'blur'} ],
goodsCategoryId: [{ required: true, message: "请填写产品类型", trigger: "blur" }], goodsCategoryId: [ {required: true, message: '请填写产品类型', trigger: 'blur'} ],
sn: [{ required: true, message: "请填写商品编码", trigger: "blur" }], sn: [ {required: true, message: '请填写商品编码', trigger: 'blur'} ],
goodsName: [{ required: true, message: "请填写产品名称", trigger: "blur" }], goodsName: [ {required: true, message: '请填写产品名称', trigger: 'blur'} ],
specParams: [{ required: true, message: "请填写规格", trigger: "blur" }], specParams: [ {required: true, message: '请填写规格', trigger: 'blur'} ],
picture: [{ required: true, message: "请填写图片", trigger: "blur" }], picture: [ {required: true, message: '请填写图片', trigger: 'blur'} ],
unit: [{ required: true, message: "请填写计量单位", trigger: "blur" }], unit: [ {required: true, message: '请填写计量单位', trigger: 'blur'} ],
sort: [{ required: true, message: "请填写排序", trigger: "blur" }], sort: [ {required: true, message: '请填写排序', trigger: 'blur'} ],
}); })
function dialogCloseHandler() { function dialogCloseHandler() {
formData.$reset(); formData.$reset()
} }
function submitHandler() { function submitHandler() {
if (status.value === "view") return; if (status.value === 'view') return
submiting.value = true; submiting.value = true
if (formData.id != null) { if (formData.id != null) {
FormUtil.submit(goodsFormIns, () => GoodsApi.modify(formData)) FormUtil.submit(goodsFormIns, () => GoodsApi.modify(formData))
.then(() => { .then(() => {
ElMessage.success("修改成功"); ElMessage.success('修改成功')
emits("editSucc"); emits('editSucc')
showDialog.value = false; showDialog.value = false
}) })
.finally(() => { .finally(() => {
submiting.value = false; submiting.value = false
}); })
} else { } else {
FormUtil.submit(goodsFormIns, () => GoodsApi.add(formData)) FormUtil.submit(goodsFormIns, () => GoodsApi.add(formData))
.then(() => { .then(() => {
ElMessage.success("添加成功"); ElMessage.success('添加成功')
emits("editSucc"); emits('editSucc')
showDialog.value = false; showDialog.value = false
}) })
.finally(() => { .finally(() => {
submiting.value = false; submiting.value = false
}); })
} }
} }
const category = ref<GoodsCategoryTypes.SearchGoodsCategoryResult[]>([]); const category = ref<GoodsCategoryTypes.SearchGoodsCategoryResult[]>([])
const loading = ref(false); const loading = ref(false)
const remoteMethod = (query: string) => { const remoteMethod = (query: string) => {
console.log(query, "query"); console.log(query, 'query')
loading.value = true; loading.value = true
GoodsCategoryApi.paging({ size: 50, categoryName: query || undefined }).then((res) => { GoodsCategoryApi.paging({size: 50, categoryName: query || undefined}).then((res) => {
category.value = res.data.records; category.value = res.data.records
loading.value = false; loading.value = false
// category.value = list.value.filter((item) => { // category.value = list.value.filter((item) => {
// return item.label.toLowerCase().includes(query.toLowerCase()) // return item.label.toLowerCase().includes(query.toLowerCase())
// }) // })
}); })
// } else { // } else {
// category.value = []; // category.value = [];
// } // }
}; }
const unitList=ref<DictItemTypes.SearchDictItemResult[]>([]) const unitList = ref<DictItemTypes.SearchDictItemResult[]>([])
const getOpt = () => { const getOpt = () => {
let searchForm = { let searchForm = {
dictKey: "unit", dictKey: 'unit',
}; }
DictApi.obtainDictData(searchForm).then((res) => { DictApi.obtainDictData(searchForm).then((res) => {
// console.log(res.data); // console.log(res.data);
unitList.value=res.data unitList.value = res.data
}); })
}; }
defineExpose({ defineExpose({
open(data: GoodsTypes.SearchGoodsResult = {}) { open(data: GoodsTypes.SearchGoodsResult = {}) {
showDialog.value = true; showDialog.value = true
if (!Strings.isBlank(data.id)) { if (!Strings.isBlank(data.id)) {
status.value = "modify"; status.value = 'modify'
GoodsApi.detail(data.id!).then((res) => { GoodsApi.detail(data.id!).then((res) => {
formData.$reset(res.data); formData.$reset(res.data)
}); if (res.data.picture != null) uploaderIns.value?.setDefaultFiles([ res.data.picture ])
})
} else { } else {
status.value = "add"; status.value = 'add'
formData.$reset(data); formData.$reset(data)
} }
getOpt(); getOpt()
}, },
}); })
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>

View File

@ -1,6 +1,6 @@
import { import {
get, get,
post post,
} from '@/common/utils/http-util.ts' } from '@/common/utils/http-util.ts'
export default { export default {
@ -19,4 +19,7 @@ export default {
del(ids: string[]) { del(ids: string[]) {
return post('/goods/del', ids) return post('/goods/del', ids)
}, },
enable(param: { enable: boolean; id: string }) {
return get('/goods/enable', param)
},
} }

View File

@ -2,64 +2,71 @@
<ElDialog v-model="showDialog" :close-on-click-modal="false" destroy-on-close width="fit-content" @close="dialogCloseHandler"> <ElDialog v-model="showDialog" :close-on-click-modal="false" destroy-on-close width="fit-content" @close="dialogCloseHandler">
<ElForm :model="formData" :rules="rules" ref="transForm" class="form-panel" label-width="auto"> <ElForm :model="formData" :rules="rules" ref="transForm" class="form-panel" label-width="auto">
<ElFormItem label-width="90" label="看料照片" prop="checkPhoto"> <ElFormItem label-width="90" label="看料照片" prop="checkPhoto">
<Uploader v-model:files="formData.checkPhoto" :limit="3" :multiple="true" accept="image/*" class="avatar-uploader" list-type="picture-card"> <Uploader v-model:files="formData.checkPhoto"
<span style="font-size: 50px; padding: 0 40px">+</span> :limit="3"
</Uploader> :upload-props="{
accept: 'image/*',
listType:'picture-card'
}"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="备注" prop="weight"> <ElFormItem label-width="90" label="备注" prop="weight">
<ElInput v-model="formData.checkerMemo" :disabled="status === 'view'" placeholder="请输入备注"> </ElInput> <ElInput v-model="formData.checkerMemo" :disabled="status === 'view'" placeholder="请输入备注"></ElInput>
</ElFormItem> </ElFormItem>
</ElForm> </ElForm>
<template #footer> <template #footer>
<ElButton @click="showDialog = false">{{ status === "view" ? "关闭" : "取消" }}</ElButton> <ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton> <ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton>
</template> </template>
</ElDialog> </ElDialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import TransApi from "@/pages/order/trans-order/trans-api.ts"; import TransApi from '@/pages/order/trans-order/trans-api.ts'
// import Strings from "@/common/utils/strings.ts"; // import Strings from "@/common/utils/strings.ts";
import FormUtil from "@/common/utils/formUtil.ts"; import FormUtil from '@/common/utils/formUtil.ts'
import Utils from "@/common/utils"; import Utils from '@/common/utils'
import { ElMessage, type FormInstance, type FormRules } from "element-plus"; import {
import Uploader from "@/components/uploader/Uploader.vue"; ElMessage,
type FormInstance,
type FormRules,
} from 'element-plus'
import Uploader from '@/components/uploader/Uploader.vue'
const emits = defineEmits(["editSucc"]); const emits = defineEmits([ 'editSucc' ])
const showDialog = ref(false); const showDialog = ref(false)
const submiting = ref(false); const submiting = ref(false)
const status = ref<"add" | "view" | "modify">("add"); const status = ref<'add' | 'view' | 'modify'>('add')
const transFormIns = useTemplateRef<FormInstance>("transForm"); const transFormIns = useTemplateRef<FormInstance>('transForm')
const formData = Utils.resetAble(reactive<TransTypes.CheckResult>({})); const formData = Utils.resetAble(reactive<TransTypes.CheckResult>({}))
const rules = reactive<FormRules<TransTypes.CheckResult>>({ const rules = reactive<FormRules<TransTypes.CheckResult>>({
orderTransId: [{ required: true, message: "请填写Id", trigger: "blur" }], orderTransId: [ {required: true, message: '请填写Id', trigger: 'blur'} ],
}); })
function dialogCloseHandler() { function dialogCloseHandler() {
formData.$reset(); formData.$reset()
} }
function submitHandler() { function submitHandler() {
// console.log(formData, "formData"); // console.log(formData, "formData");
// return; // return;
if (status.value === "view") return; if (status.value === 'view') return
submiting.value = true; submiting.value = true
FormUtil.submit(transFormIns, () => { FormUtil.submit(transFormIns, () => {
let data = Object.assign({}, formData); let data = Object.assign({}, formData)
return TransApi.check(data); return TransApi.check(data)
}) })
.then(() => { .then(() => {
ElMessage.success("看料成功"); ElMessage.success('看料成功')
emits("editSucc"); emits('editSucc')
showDialog.value = false; showDialog.value = false
}) })
.finally(() => { .finally(() => {
submiting.value = false; submiting.value = false
}); })
// if (formData.id != null) { // if (formData.id != null) {
// FormUtil.submit(transFormIns, () => TransApi.modify(formData)) // FormUtil.submit(transFormIns, () => TransApi.modify(formData))
@ -86,10 +93,10 @@ function submitHandler() {
defineExpose({ defineExpose({
open(data: TransTypes.SearchTransResult = {}) { open(data: TransTypes.SearchTransResult = {}) {
formData.orderTransId = data.id; formData.orderTransId = data.id
showDialog.value = true; showDialog.value = true
}, },
}); })
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>

View File

@ -8,70 +8,78 @@
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="车头照" prop="cargoPhoto"> <ElFormItem label-width="90" label="车头照" prop="cargoPhoto">
<Uploader v-model:file="formData.cargoPhoto" :limit="1" :multiple="true" accept="image/*" class="avatar-uploader" list-type="picture-card"> <Uploader v-model:file="formData.cargoPhoto"
<span style="font-size: 50px; padding: 0 40px">+</span> :upload-props="{
</Uploader> accept: 'image/*',
listType:'picture-card'
}"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="车斗照" prop="bodyPhoto"> <ElFormItem label-width="90" label="车斗照" prop="bodyPhoto">
<Uploader v-model:file="formData.bodyPhoto" :limit="1" :multiple="true" accept="image/*" class="avatar-uploader" list-type="picture-card"> <Uploader v-model:file="formData.bodyPhoto"
<span style="font-size: 50px; padding: 0 40px">+</span> :upload-props="{
</Uploader> accept: 'image/*',
listType:'picture-card'
}"/>
</ElFormItem> </ElFormItem>
</ElForm> </ElForm>
<template #footer> <template #footer>
<ElButton @click="showDialog = false">{{ status === "view" ? "关闭" : "取消" }}</ElButton> <ElButton @click="showDialog = false">{{ status === 'view' ? '关闭' : '取消' }}</ElButton>
<ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton> <ElButton v-if="status !== 'view'" :loading="submiting" type="primary" @click="submitHandler"></ElButton>
</template> </template>
</ElDialog> </ElDialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import TransApi from "@/pages/order/trans-order/trans-api.ts"; import TransApi from '@/pages/order/trans-order/trans-api.ts'
// import Strings from "@/common/utils/strings.ts"; // import Strings from "@/common/utils/strings.ts";
import FormUtil from "@/common/utils/formUtil.ts"; import FormUtil from '@/common/utils/formUtil.ts'
import Utils from "@/common/utils"; import Utils from '@/common/utils'
import { ElMessage, type FormInstance, type FormRules } from "element-plus"; import {
import Uploader from "@/components/uploader/Uploader.vue"; ElMessage,
type FormInstance,
type FormRules,
} from 'element-plus'
import Uploader from '@/components/uploader/Uploader.vue'
const emits = defineEmits(["editSucc"]); const emits = defineEmits([ 'editSucc' ])
const showDialog = ref(false); const showDialog = ref(false)
const submiting = ref(false); const submiting = ref(false)
const status = ref<"add" | "view" | "modify">("add"); const status = ref<'add' | 'view' | 'modify'>('add')
const transFormIns = useTemplateRef<FormInstance>("transForm"); const transFormIns = useTemplateRef<FormInstance>('transForm')
const formData = Utils.resetAble(reactive<TransTypes.InOutResult>({ const formData = Utils.resetAble(reactive<TransTypes.InOutResult>({
weight:0 weight: 0,
})); }))
const rules = reactive<FormRules<TransTypes.InOutResult>>({ const rules = reactive<FormRules<TransTypes.InOutResult>>({
orderTransId: [{ required: true, message: "请填写Id", trigger: "blur" }], orderTransId: [ {required: true, message: '请填写Id', trigger: 'blur'} ],
cargoPhoto: [{ required: true, message: "请上传车头照", trigger: "blur" }], cargoPhoto: [ {required: true, message: '请上传车头照', trigger: 'blur'} ],
bodyPhoto: [{ required: true, message: "请上传车尾照", trigger: "blur" }], bodyPhoto: [ {required: true, message: '请上传车尾照', trigger: 'blur'} ],
weight: [{ required: true, message: "请输入磅重", trigger: "blur" }], weight: [ {required: true, message: '请输入磅重', trigger: 'blur'} ],
}); })
function dialogCloseHandler() { function dialogCloseHandler() {
formData.$reset(); formData.$reset()
} }
function submitHandler() { function submitHandler() {
if (status.value === "view") return; if (status.value === 'view') return
submiting.value = true; submiting.value = true
FormUtil.submit(transFormIns, () => { FormUtil.submit(transFormIns, () => {
let data = Object.assign({}, formData); let data = Object.assign({}, formData)
data.weight = data.weight * 1000; data.weight = data.weight * 1000
return TransApi.coming(data); return TransApi.coming(data)
}) })
.then(() => { .then(() => {
ElMessage.success("进场成功"); ElMessage.success('进场成功')
emits("editSucc"); emits('editSucc')
showDialog.value = false; showDialog.value = false
}) })
.finally(() => { .finally(() => {
submiting.value = false; submiting.value = false
}); })
// if (formData.id != null) { // if (formData.id != null) {
// FormUtil.submit(transFormIns, () => TransApi.modify(formData)) // FormUtil.submit(transFormIns, () => TransApi.modify(formData))
@ -98,10 +106,10 @@ function submitHandler() {
defineExpose({ defineExpose({
open(data: TransTypes.SearchTransResult = {}) { open(data: TransTypes.SearchTransResult = {}) {
formData.orderTransId = data.id; formData.orderTransId = data.id
showDialog.value = true; showDialog.value = true
}, },
}); })
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>

View File

@ -8,15 +8,19 @@
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="车头照" prop="cargoPhoto"> <ElFormItem label-width="90" label="车头照" prop="cargoPhoto">
<Uploader v-model:file="formData.cargoPhoto" :limit="1" :multiple="true" accept="image/*" class="avatar-uploader" list-type="picture-card"> <Uploader v-model:file="formData.cargoPhoto"
<span style="font-size: 50px; padding: 0 40px">+</span> :upload-props="{
</Uploader> accept: 'image/*',
listType:'picture-card'
}"/>
</ElFormItem> </ElFormItem>
<ElFormItem label-width="90" label="车斗照" prop="bodyPhoto"> <ElFormItem label-width="90" label="车斗照" prop="bodyPhoto">
<Uploader v-model:file="formData.bodyPhoto" :limit="1" :multiple="true" accept="image/*" class="avatar-uploader" list-type="picture-card"> <Uploader v-model:file="formData.bodyPhoto"
<span style="font-size: 50px; padding: 0 40px">+</span> :upload-props="{
</Uploader> accept: 'image/*',
listType:'picture-card'
}"/>
</ElFormItem> </ElFormItem>
</ElForm> </ElForm>
<template #footer> <template #footer>
@ -27,12 +31,16 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import TransApi from "@/pages/order/trans-order/trans-api.ts"; import TransApi from '@/pages/order/trans-order/trans-api.ts'
// import Strings from "@/common/utils/strings.ts"; // import Strings from "@/common/utils/strings.ts";
import FormUtil from "@/common/utils/formUtil.ts"; import FormUtil from '@/common/utils/formUtil.ts'
import Utils from "@/common/utils"; import Utils from '@/common/utils'
import { ElMessage, type FormInstance, type FormRules } from "element-plus"; import {
import Uploader from "@/components/uploader/Uploader.vue"; ElMessage,
type FormInstance,
type FormRules,
} from 'element-plus'
import Uploader from '@/components/uploader/Uploader.vue'
const emits = defineEmits(["editSucc"]); const emits = defineEmits(["editSucc"]);
const showDialog = ref(false); const showDialog = ref(false);

View File

@ -18,11 +18,10 @@
<Uploader <Uploader
v-model:file="userFormData.avatar" v-model:file="userFormData.avatar"
:disabled="status === 'view'" :disabled="status === 'view'"
:limit="1" :upload-props="{
:multiple="true" accept: 'image/*',
accept="image/*" listType:'picture'
class="avatar-uploader" }">
list-type="picture">
<ElButton>点击上传头像</ElButton> <ElButton>点击上传头像</ElButton>
</Uploader> </Uploader>
</ElFormItem> </ElFormItem>