feat: 更新代码

This commit is contained in:
华珑 2025-02-18 20:11:39 +08:00
parent 0516ee998e
commit 71f3e8d415
15 changed files with 383 additions and 75 deletions

View File

@ -12,6 +12,14 @@ body,
overflow: hidden; overflow: hidden;
} }
/*
.ant-input-affix-wrapper-readonly,
.ant-input[readonly],
.ant-input-affix-wrapper-readonly .ant-input {
background-color: #fafafa;
cursor: default;
}
*/
@keyframes rotate { @keyframes rotate {
0% { 0% {
transform: rotate(0deg) transform: rotate(0deg)

View File

@ -2,13 +2,20 @@
import { watch, ref, onMounted } from 'vue'; import { watch, ref, onMounted } from 'vue';
import { Button } from '../../common'; import { Button } from '../../common';
import { Modal, Space } from 'ant-design-vue'; import { Modal, Space } from 'ant-design-vue';
import { AsyncUploader, EditorData, PageData } from '@skyfox2000/webbase'; import { AsyncUploader, EditorData, gridRowUpdate, PageData } from '@skyfox2000/webbase';
import { AnyData, IUrlInfo } from '@skyfox2000/fapi'; import { AnyData, ApiResponse, IUrlInfo, ResStatus } from '@skyfox2000/fapi';
import UploadFileList from './uploadList.vue'; import UploadFileList from './uploadList.vue';
import { UploadFile } from '@skyfox2000/webbase'; import { UploadFile } from '@skyfox2000/webbase';
import message from 'vue-m-message'; import message from 'vue-m-message';
import { UploadStatus } from '@skyfox2000/webbase';
const props = defineProps<{ const props = defineProps<{
/**
* #### 使用模式
* - Row 数据行
* - Page 页面
*/
mode: 'Row' | 'Page';
/** /**
* 文件后缀限制 * 文件后缀限制
*/ */
@ -44,6 +51,20 @@ const maxCount = props.maxCount ?? 1;
const maxConcurrent = props.maxConcurrent ?? 3; const maxConcurrent = props.maxConcurrent ?? 3;
const fileList = ref<UploadFile[]>([]); const fileList = ref<UploadFile[]>([]);
const emit = defineEmits<{
/**
* 显示预处理
*/
'before:file-list': [EditorData<any>, UploadFile[]];
/**
* 上传前预处理
*/
'before:upload': [UploadFile[]];
/**
* 上传结束处理上传后的文件
*/
'after:upload': [UploadFile[]];
}>();
watch( watch(
() => uploaderForm.value.visible, () => uploaderForm.value.visible,
@ -62,36 +83,64 @@ const dialogUpload = async () => {
if (!url.api) url.api = props.pageData.api; if (!url.api) url.api = props.pageData.api;
if (url.authorize === undefined) url.authorize = props.pageData.authorize; if (url.authorize === undefined) url.authorize = props.pageData.authorize;
emit('before:upload', fileList.value);
const uploader = new AsyncUploader(url, maxConcurrent); const uploader = new AsyncUploader(url, maxConcurrent);
uploaderForm.value.isFormLoading = true; uploaderForm.value.isFormLoading = true;
try { try {
if (fileList.value.length === 0) { if (fileList.value.length === 0) {
message.warning('请选择上传的文件!'); message.warning('请选择上传的文件!');
setTimeout(() => {
uploaderForm.value.isFormLoading = false;
}, 10000);
return; return;
} }
// //
await uploader.upload( await uploader.upload(
fileList.value, fileList.value,
(file) => { (_) => {},
console.log(`${file.name} 上传进度:${file.percent}% (${file.status})`);
},
(files) => { (files) => {
uploaderForm.value.isFormLoading = false; uploaderForm.value.isFormLoading = false;
console.log('所有文件上传结束:', files); let err_count = 0;
for (const file of files) {
if (file.status === UploadStatus.Error) {
err_count++;
}
}
if (!err_count) message.success('全部文件上传成功!');
else if (err_count < files.length) message.error('上传结束,部分文件上传失败!');
else message.error('上传结束,所有文件上传失败!');
// formData
emit('after:upload', files);
dialogSave();
}, },
); );
} catch (error) { } catch (error) {
uploaderForm.value.isFormLoading = false; uploaderForm.value.isFormLoading = false;
console.error('上传错误:', error); console.error('上传错误:', error);
message.error('上传错误,请稍后再试!');
emit('after:upload', fileList.value);
}
};
const dialogSave = async () => {
switch (props.mode) {
case 'Row':
if (uploaderForm.value.formData) {
//
const result: ApiResponse<any> = await gridRowUpdate(props.pageData, uploaderForm.value.formData);
if (result.status === ResStatus.SUCCESS) {
uploaderForm.value.visible = false;
}
}
break;
case 'Page':
break;
} }
}; };
onMounted(() => { onMounted(() => {
const list: UploadFile[] = [];
emit('before:file-list', uploaderForm.value, list);
fileList.value.push(...list);
open.value = uploaderForm.value.visible; open.value = uploaderForm.value.visible;
}); });
@ -106,11 +155,11 @@ const dialogClose = () => {
:wrapClassName="'modal mx-auto ' + ($attrs.width ? 'w-[' + $attrs.width + ']' : 'w-[430px]')" :wrapClassName="'modal mx-auto ' + ($attrs.width ? 'w-[' + $attrs.width + ']' : 'w-[430px]')"
@close="dialogClose" @close="dialogClose"
> >
<UploadFileList v-model:file-list="fileList" :max-count="maxCount" :file-ext="fileExt" /> <UploadFileList v-model:file-list="fileList" :page-data="pageData" :max-count="maxCount" :file-ext="fileExt" />
<template #footer> <template #footer>
<Space> <Space>
<Button @click="dialogClose">取消</Button> <Button @click="dialogClose">取消</Button>
<Button @click="dialogUpload" type="primary" :loading="uploaderForm.isFormSaving"> 上传文件 </Button> <Button @click="dialogUpload" type="primary" :loading="uploaderForm.isFormSaving"> 上传文件并保存 </Button>
</Space> </Space>
</template> </template>
</Modal> </Modal>

View File

@ -1,30 +1,53 @@
<script setup lang="ts"> <script setup lang="ts">
import { Button } from '@/components'; import { Button } from '@/components';
import { computed, ref } from 'vue'; import { computed, ref, watch } from 'vue';
import message from 'vue-m-message'; import message from 'vue-m-message';
import type { UploadProps } from 'ant-design-vue'; import type { UploadProps } from 'ant-design-vue';
import { Upload, Progress, Tag } from 'ant-design-vue'; import { Upload, Progress, Tag } from 'ant-design-vue';
import { UploadFile, UploadFileStatus } from '@skyfox2000/webbase'; import { PageData, UploadFile, UploadStatus, donwloadFromMinio, path } from '@skyfox2000/webbase';
import { watch } from 'vue'; import { IUrlInfo } from '@skyfox2000/fapi';
interface Props { interface Props {
fileList: UploadFile<any>[]; /**
placeholder?: string; * 是否自动上传
fileExt?: string[]; */
maxFileSize?: number;
maxCount?: number;
autoUpload?: boolean; autoUpload?: boolean;
pageData: PageData<any>;
/**
* 文件列表
*/
fileList: UploadFile<any>[];
/**
* 提示文字
*/
placeholder?: string;
/**
* 文件后缀列表
*/
fileExt?: string[];
/**
* 最大文件大小
*/
maxFileSize?: number;
/**
* 最大数量
*/
maxCount?: number;
/**
* 文件路径
*/
parentPath?: string;
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
autoUpload: false,
fileList: () => [], fileList: () => [],
placeholder: '', placeholder: '',
maxFileSize: 20, maxFileSize: 20,
maxCount: 5, maxCount: 5,
autoUpload: false,
}); });
const fileList = ref<UploadFile[]>([]); const fileList = ref<UploadFile[]>(props.fileList);
const fileUploader = ref(); const fileUploader = ref();
const emit = defineEmits(['update:file-list']); const emit = defineEmits(['update:file-list']);
@ -44,7 +67,7 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
return false; return false;
} }
if (fileList.value.length >= props.maxCount) { if (props.maxCount > 1 && fileList.value.length >= props.maxCount) {
message.error(`最多上传 ${props.maxCount} 个文件`); message.error(`最多上传 ${props.maxCount} 个文件`);
return false; return false;
} }
@ -52,10 +75,18 @@ const beforeUpload: UploadProps['beforeUpload'] = (file) => {
return props.autoUpload; return props.autoUpload;
}; };
const updateFileList: UploadProps['onUpdate:fileList'] = (fileList) => {
fileList.forEach((file) => {
if (!file.fileName) file.fileName = file.name;
if (props.parentPath) file.name = path.join('/', props.parentPath, file.fileName);
});
};
const uploadProps = computed<UploadProps>(() => ({ const uploadProps = computed<UploadProps>(() => ({
accept: acceptString.value, accept: acceptString.value,
multiple: true, multiple: true,
fileList: fileList.value as UploadProps['fileList'], fileList: fileList.value as UploadProps['fileList'],
'onUpdate:fileList': updateFileList,
beforeUpload: beforeUpload, beforeUpload: beforeUpload,
listType: 'text', listType: 'text',
maxCount: props.maxCount, maxCount: props.maxCount,
@ -75,6 +106,36 @@ watch(
{ deep: true }, { deep: true },
); );
const downloadFile = (index: number) => {
const fileInfo = fileList.value[index].minioFile!;
const url: IUrlInfo = {
api: props.pageData.api,
authorize: props.pageData.authorize,
url: props.pageData.urls.download!.url,
params: {
Query: {
FileKey: fileInfo.Key,
},
},
};
donwloadFromMinio(url);
};
const onlineOrOffline = (file: UploadFile) => {
file.status = file.status === UploadStatus.Offline ? UploadStatus.Online : UploadStatus.Offline;
file.minioFile!.Status = file.status;
};
// const previewFile = (index: number) => {
// const fileInfo = fileList.value[index].minioFile;
// console.log(fileInfo);
// };
const removeFile = (index: number) => {
fileList.value.splice(index, 1);
};
const getPlaceholder = (): string => { const getPlaceholder = (): string => {
const typeMsg = props.fileExt && props.fileExt.length ? `文件必须为 ${props.fileExt.join('/')}` : ''; const typeMsg = props.fileExt && props.fileExt.length ? `文件必须为 ${props.fileExt.join('/')}` : '';
const sizeMsg = props.maxFileSize !== 0 ? `单文件最大 ${props.maxFileSize}MB` : ''; const sizeMsg = props.maxFileSize !== 0 ? `单文件最大 ${props.maxFileSize}MB` : '';
@ -83,30 +144,34 @@ const getPlaceholder = (): string => {
return [sizeMsg, typeMsg, countMsg].filter(Boolean).join(''); return [sizeMsg, typeMsg, countMsg].filter(Boolean).join('');
}; };
const removeFile = (index: number) => { const getStatusColor = (status?: UploadStatus) => {
fileList.value.splice(index, 1);
};
const getStatusColor = (status?: UploadFileStatus) => {
switch (status) { switch (status) {
case UploadFileStatus.Uploading: case UploadStatus.Uploading:
return 'blue'; return 'blue';
case UploadFileStatus.Success: case UploadStatus.Success:
return 'green'; return 'green';
case UploadFileStatus.Error: case UploadStatus.Error:
return 'red'; return 'red';
case UploadStatus.Online:
return 'green';
case UploadStatus.Offline:
return 'pink';
default: default:
return 'cyan'; return 'cyan';
} }
}; };
const getStatus = (status?: UploadFileStatus) => { const getStatus = (status?: UploadStatus) => {
switch (status) { switch (status) {
case UploadFileStatus.Uploading: case UploadStatus.Uploading:
return '上传中'; return '上传中';
case UploadFileStatus.Success: case UploadStatus.Success:
return '已完成'; return '已完成';
case UploadFileStatus.Error: case UploadStatus.Error:
return '上传失败'; return '上传失败';
case UploadStatus.Online:
return '在线';
case UploadStatus.Offline:
return '已下线';
default: default:
return '待上传'; return '待上传';
} }
@ -129,20 +194,36 @@ const getStatus = (status?: UploadFileStatus) => {
<div v-for="(file, index) in fileList" :key="index" class="mb-2 pb-1"> <div v-for="(file, index) in fileList" :key="index" class="mb-2 pb-1">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="flex items-center"> <div class="flex items-center">
<span class="text-gray-700 mr-2">{{ file.name }}</span> <span
class="text-gray-700 mr-2"
:class="[file.status == UploadStatus.Offline ? 'line-through' : '']"
>{{ file.fileName ?? file.name }}</span
>
<span> <span>
<Tag :color="getStatusColor(file.status)">{{ getStatus(file.status) }}</Tag> <Tag :color="getStatusColor(file.status)">{{ getStatus(file.status) }}</Tag>
</span> </span>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<!-- <span class="text-blue-500 hover:text-blue-700 mr-4">预览</span> --> <span
class="text-blue-500 hover:text-blue-700 mr-4 cursor-pointer"
v-if="file.status == UploadStatus.Offline || file.status == UploadStatus.Online"
@click="onlineOrOffline(file)"
>{{ file.status == UploadStatus.Offline ? '上线' : '下线' }}</span
>
<span
v-if="file.status == UploadStatus.Offline || file.status == UploadStatus.Online"
class="text-blue-500 hover:text-blue-700 mr-4 cursor-pointer"
@click="downloadFile(index)"
>下载</span
>
<!-- <span class="text-blue-500 hover:text-blue-700 mr-4" @click="previewFile(index)">预览</span> -->
<span class="text-red-500 hover:text-red-700 cursor-pointer" @click="removeFile(index)">删除</span> <span class="text-red-500 hover:text-red-700 cursor-pointer" @click="removeFile(index)">删除</span>
</div> </div>
</div> </div>
<!-- 上传进度条 --> <!-- 上传进度条 -->
<div> <div>
<Progress :percent="file.percent" :stroke-width="2" :show-info="false" style="height: 2px" /> <Progress :percent="file.percent" :stroke-width="2" :show-info="false" style="height: 2px"></Progress>
</div> </div>
</div> </div>
</div> </div>

View File

@ -86,6 +86,7 @@ const disabled = (item: ButtonTool) => {
<Space> <Space>
<template v-for="item in Buttons" :key="item.key"> <template v-for="item in Buttons" :key="item.key">
<Popconfirm <Popconfirm
v-if="getToolVisible(item, props.record)"
:disabled="!item.confirm" :disabled="!item.confirm"
cancelText="否" cancelText="否"
okText="是" okText="是"
@ -98,7 +99,7 @@ const disabled = (item: ButtonTool) => {
:key="item.key" :key="item.key"
:type="item.type ?? 'text'" :type="item.type ?? 'text'"
:danger="item.danger" :danger="item.danger"
v-if="getToolVisible(item)" v-if="getToolVisible(item, props.record)"
:disabled="disabled(item)" :disabled="disabled(item)"
@click="onToolClicked(item, pageData, props.record)" @click="onToolClicked(item, pageData, props.record)"
size="small" size="small"
@ -118,7 +119,7 @@ const disabled = (item: ButtonTool) => {
<Menu> <Menu>
<template v-for="item in Menus" :key="item.key"> <template v-for="item in Menus" :key="item.key">
<MenuItem <MenuItem
v-if="getToolVisible(item)" v-if="getToolVisible(item, props.record)"
:disabled="disabled(item)" :disabled="disabled(item)"
@click="onToolClicked(item, pageData, props.record)" @click="onToolClicked(item, pageData, props.record)"
> >

View File

@ -45,7 +45,7 @@ const onClear = () => {
</script> </script>
<template> <template>
<Input <Input
:class="errClass === 'error' ? ['error', '!border-red-300', 'shadow-[0_0_3px_0px_#ff4d4f]'] : ''" :class="[errClass === 'error' ? 'error !border-red-300 shadow-[0_0_3px_0px_#ff4d4f]' : '']"
v-model:value="innerValue" v-model:value="innerValue"
@change="onClear" @change="onClear"
:allow-clear="true" :allow-clear="true"

12
src/types/global.d.ts vendored
View File

@ -53,6 +53,10 @@ declare global {
* ID * ID
*/ */
Id: string | null; Id: string | null;
/**
*
*/
OrderNo: string | null;
/** /**
* *
*/ */
@ -61,6 +65,10 @@ declare global {
* *
*/ */
MemberName: string | null; MemberName: string | null;
/**
*
*/
Mobile: string | null;
/** /**
* ID * ID
*/ */
@ -84,11 +92,11 @@ declare global {
/** /**
* *
*/ */
ExpressInfo?: { [key: string]: any }; ExpressInfo?: Record;
/** /**
* *
*/ */
ReportFileUrl?: string | null; ReportFile?: MinioFile[];
/** /**
* *
*/ */

View File

@ -24,6 +24,12 @@ export const SamplingHelperUrl: ApiUrls = {
save: { save: {
url: '/api/RCSamplingHelperSrv/save', url: '/api/RCSamplingHelperSrv/save',
}, },
/**
*
*/
update: {
url: '/api/RCSamplingHelperSrv/update',
},
/** /**
* *
*/ */

View File

@ -10,14 +10,20 @@ const formData = ref<OrderEntity>(editorData.formData);
<template> <template>
<Drawer title="订单信息" :page-data="pageData"> <Drawer title="订单信息" :page-data="pageData">
<Form> <Form>
<FormItem label="订单号">
<Input v-model:value="formData.OrderNo" disabled />
</FormItem>
<FormItem label="会员名"> <FormItem label="会员名">
<Input v-model:value="formData.MemberName" /> <Input v-model:value="formData.MemberName" disabled />
</FormItem>
<FormItem label="手机号">
<Input v-model:value="formData.Mobile" disabled />
</FormItem> </FormItem>
<FormItem label="产品名称"> <FormItem label="产品名称">
<Input v-model:value="formData.ProductName" /> <Input v-model:value="formData.ProductName" disabled />
</FormItem> </FormItem>
<FormItem label="价码"> <FormItem label="价码">
<Input v-model:value="formData.PriceCode" /> <Input v-model:value="formData.PriceCode" disabled />
</FormItem> </FormItem>
<FormItem label="快递号"> <FormItem label="快递号">
<Input v-model:value="formData.ExpressNumber" /> <Input v-model:value="formData.ExpressNumber" />
@ -26,7 +32,7 @@ const formData = ref<OrderEntity>(editorData.formData);
<Status v-model:value="formData.Status" /> <Status v-model:value="formData.Status" />
</FormItem> </FormItem>
<FormItem label="备注"> <FormItem label="备注">
<Textarea v-model:value="formData.Remark" :auto-size="{ minRows: 3, maxRows: 6 }" /> <Textarea v-model:value="formData.Remark" :auto-size="{ minRows: 3, maxRows: 6 }" />
</FormItem> </FormItem>
</Form> </Form>
</Drawer> </Drawer>

View File

@ -5,6 +5,8 @@ import UploadForm from '@/components/content/dialog/uploadForm.vue';
import Grid from './grid.vue'; import Grid from './grid.vue';
import Search from './search.vue'; import Search from './search.vue';
import { pageData, usePageInit } from './page'; import { pageData, usePageInit } from './page';
import { beforeFileList, afterUpload, beforeUpload } from './upload';
usePageInit(); usePageInit();
// //
@ -18,7 +20,11 @@ const Editor = defineAsyncComponent(() => import('./editor.vue'));
<component :is="Editor" v-if="pageData.editor?.visible" /> <component :is="Editor" v-if="pageData.editor?.visible" />
<UploadForm <UploadForm
v-if="pageData.subEditor!.uploadForm.visible" v-if="pageData.subEditor!.uploadForm.visible"
@before:file-list="beforeFileList"
@before:upload="beforeUpload"
@after:upload="afterUpload"
width="600px" width="600px"
mode="Row"
:upload-form="pageData.subEditor!.uploadForm" :upload-form="pageData.subEditor!.uploadForm"
:max-count="1" :max-count="1"
:page-data="pageData" :page-data="pageData"

View File

@ -1,3 +1,4 @@
import { MinioFile } from '@skyfox2000/webbase';
/** /**
* *
*/ */
@ -6,6 +7,10 @@ export interface OrderEntity {
* ID * ID
*/ */
Id: string | null; Id: string | null;
/**
*
*/
OrderNo: string | null;
/** /**
* *
*/ */
@ -14,6 +19,10 @@ export interface OrderEntity {
* *
*/ */
MemberName: string | null; MemberName: string | null;
/**
*
*/
Mobile: string | null;
/** /**
* ID * ID
*/ */
@ -37,11 +46,11 @@ export interface OrderEntity {
/** /**
* *
*/ */
ExpressInfo?: { [key: string]: any }; ExpressInfo?: Record;
/** /**
* *
*/ */
ReportFileUrl?: string | null; ReportFile?: MinioFile[];
/** /**
* *
*/ */

View File

@ -2,7 +2,15 @@
* *
* API操作 * API操作
*/ */
import { usePageFactory, ApiUrls, ValidateRule, ButtonTool, exportSelectedRows, EditorData } from '@skyfox2000/webbase'; import {
usePageFactory,
ApiUrls,
ValidateRule,
ButtonTool,
exportSelectedRows,
isEmpty,
PageData,
} from '@skyfox2000/webbase';
import { ref } from 'vue'; import { ref } from 'vue';
import message from 'vue-m-message'; import message from 'vue-m-message';
@ -32,12 +40,16 @@ export const OrderUrl: ApiUrls = {
url: '/api/RCOrderSrv/remove', url: '/api/RCOrderSrv/remove',
}, },
update: {
url: '/api/RCOrderSrv/update',
},
upload: { upload: {
url: '', url: '/api/FileSrv/upload',
header: { },
'Content-Type': 'multipart/form-data',
}, download: {
authorize: true, // 需要授权 url: '/api/FileSrv/download',
}, },
}, },
}; };
@ -47,15 +59,17 @@ export const OrderUrl: ApiUrls = {
*/ */
const defaultData: OrderEntity = { const defaultData: OrderEntity = {
Id: null, Id: null,
OrderNo: null,
MemberId: null, MemberId: null,
MemberName: null, MemberName: null,
Mobile: null,
PriceId: null, PriceId: null,
PriceCode: null, PriceCode: null,
ProductName: null, ProductName: null,
Address: null, Address: null,
ExpressNumber: null, ExpressNumber: null,
ExpressInfo: {}, ExpressInfo: {},
ReportFileUrl: null, ReportFile: [],
Status: null, Status: null,
Remark: null, Remark: null,
Enabled: 1, Enabled: 1,
@ -98,25 +112,34 @@ const columns = ref([
{ {
title: '订单号', title: '订单号',
dataIndex: 'OrderNo', dataIndex: 'OrderNo',
width: 120, width: 100,
responsive: ['md'], responsive: ['md'],
}, },
{ {
title: '会员名', title: '会员名',
dataIndex: 'MemberName', dataIndex: 'MemberName',
width: 120, width: 60,
responsive: ['md'], responsive: ['md'],
}, },
{ {
title: '手机号', title: '手机号',
dataIndex: 'Mobile', dataIndex: 'Mobile',
width: 120, width: 110,
responsive: ['md'], responsive: ['md'],
}, },
{ {
title: '价码', title: '订单日期',
dataIndex: 'PriceCode', dataIndex: 'PriceCode',
width: 90,
customRender: ({ record }: { record: OrderEntity }) => {
return record.CreateTime!.substring(0, 10);
},
},
{
title: '产品',
dataIndex: 'ProductName',
width: 100, width: 100,
ellipsis: true,
responsive: ['lg'], responsive: ['lg'],
}, },
{ {
@ -129,7 +152,7 @@ const columns = ref([
{ {
title: '订单状态', title: '订单状态',
dataIndex: 'Status', dataIndex: 'Status',
width: 100, width: 70,
responsive: ['md'], responsive: ['md'],
}, },
{ {
@ -146,6 +169,7 @@ gridData.remotePage = false;
gridData.selectKeys = []; gridData.selectKeys = [];
gridData.selectRows = []; gridData.selectRows = [];
gridData.selectable = true; gridData.selectable = true;
let download: ButtonTool = { let download: ButtonTool = {
label: '下载', label: '下载',
key: 'download', key: 'download',
@ -159,18 +183,8 @@ let download: ButtonTool = {
} }
}, },
}; };
gridData.buttons = ['New', download]; gridData.buttons = [download];
import { OrderEntity } from './model';
// 文件上传弹窗
let uploadForm: EditorData<OrderEntity> = {
visible: false,
formData: JSON.parse(JSON.stringify(defaultData)),
isFormSaving: false,
isFormLoading: false,
};
pageData.value.subEditor = {
uploadForm,
};
gridData.tools = ['Reload', 'Fullscreen']; gridData.tools = ['Reload', 'Fullscreen'];
let upload: ButtonTool = { let upload: ButtonTool = {
@ -178,9 +192,44 @@ let upload: ButtonTool = {
key: 'upload', key: 'upload',
type: 'default', type: 'default',
icon: 'icon-upload', icon: 'icon-upload',
click: (_, row) => { visible: (row: OrderEntity) => {
pageData.value.subEditor!.uploadForm.formData = row; if (!row || isEmpty(row.ReportFile)) {
return true;
}
return false;
},
click: <T>(_: PageData<T>, row: T) => {
const rowData = row as OrderEntity;
pageData.value.subEditor!.uploadForm.formData = {
Id: rowData.Id,
OrderNo: rowData.OrderNo,
Mobile: rowData.Mobile,
ReportFile: rowData.ReportFile,
};
pageData.value.subEditor!.uploadForm.visible = !pageData.value.subEditor!.uploadForm.visible; pageData.value.subEditor!.uploadForm.visible = !pageData.value.subEditor!.uploadForm.visible;
}, },
}; };
gridData.operates = [upload, 'Edit', 'Delete'];
let view: ButtonTool = {
label: '查看报告',
key: 'view',
type: 'default',
icon: 'icon-view',
visible: (row: OrderEntity) => {
if (row && !isEmpty(row.ReportFile)) {
return true;
}
return false;
},
click: <T>(_: PageData<T>, row: T) => {
const rowData = row as OrderEntity;
pageData.value.subEditor!.uploadForm.formData = {
Id: rowData.Id,
OrderNo: rowData.OrderNo,
Mobile: rowData.Mobile,
ReportFile: rowData.ReportFile,
};
pageData.value.subEditor!.uploadForm.visible = !pageData.value.subEditor!.uploadForm.visible;
},
};
gridData.operates = [upload, view, 'Edit', 'Delete'];

View File

@ -0,0 +1,67 @@
import { EditorData, isEmpty, MinioFile, path, UploadFile, UploadStatus } from '@skyfox2000/webbase';
import { OrderUrl, pageData } from './page';
import dayjs from 'dayjs';
// 文件上传弹窗
let uploadForm: EditorData<Record<string, any>> = {
visible: false,
formData: {},
isFormSaving: false,
isFormLoading: false,
saveUrl: OrderUrl.urls.update,
};
pageData.value.subEditor = {
uploadForm,
};
export const beforeFileList = (editorData: EditorData<OrderEntity>, fileList: UploadFile[]) => {
if (!isEmpty(editorData.formData?.ReportFile)) {
for (const reportFile of editorData.formData?.ReportFile!) {
const minioFile = reportFile as MinioFile;
const file: UploadFile = {
uid: minioFile.ETag,
name: minioFile.Key,
fileName: minioFile.FileName!,
lastModifiedDate: dayjs(minioFile.UpdateTime).toDate(),
status: minioFile.Status ?? UploadStatus.Online,
percent: 0,
params: {},
minioFile: minioFile,
};
minioFile.Status = file.status!;
fileList.push(file);
}
}
};
export const beforeUpload = (files: UploadFile[]) => {
files.forEach((file) => {
file.name = path.join(
'/Order/ReportFile',
uploadForm.formData.Mobile,
uploadForm.formData.OrderNo,
file.fileName!,
);
file.params = {
FileKey: file.name,
};
});
};
export const afterUpload = (files: UploadFile[]) => {
const uploadFiles: Record<string, any>[] = [];
files.forEach((file) => {
if (
(file.status == UploadStatus.Success ||
file.status == UploadStatus.Online ||
file.status == UploadStatus.Offline) &&
file.minioFile
) {
file.minioFile.FileName = file.fileName!;
uploadFiles.push(file.minioFile);
}
});
/// 为空的话,即删除所有上传的文件
uploadForm.formData!.ReportFile = uploadFiles;
};

View File

@ -24,6 +24,12 @@ export const PriceQRUrl: ApiUrls = {
save: { save: {
url: '/api/RCPriceQRSrv/save', url: '/api/RCPriceQRSrv/save',
}, },
/**
*
*/
update: {
url: '/api/RCPriceQRSrv/update',
},
/** /**
* *
*/ */

View File

@ -24,6 +24,12 @@ export const AccountUrl: ApiUrls = {
save: { save: {
url: '/api/RCAccountOpSrv/save', url: '/api/RCAccountOpSrv/save',
}, },
/**
*
*/
update: {
url: '/api/RCAccountOpSrv/update',
},
/** /**
* *
*/ */

View File

@ -28,6 +28,12 @@ export const DoctorUrl: ApiUrls = {
save: { save: {
url: '/api/RCDoctorSrv/save', url: '/api/RCDoctorSrv/save',
}, },
/**
*
*/
update: {
url: '/api/RCDoctorSrv/update',
},
/** /**
* *
*/ */