Compare commits
4 Commits
dd220a3417
...
f83c8bfb76
Author | SHA1 | Date | |
---|---|---|---|
f83c8bfb76 | |||
dee085bbed | |||
49c832e94f | |||
69bae8de3a |
@ -31,6 +31,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
monitor_logininfor: () => import("@/views/monitor/logininfor/index.vue"),
|
monitor_logininfor: () => import("@/views/monitor/logininfor/index.vue"),
|
||||||
monitor_online: () => import("@/views/monitor/online/index.vue"),
|
monitor_online: () => import("@/views/monitor/online/index.vue"),
|
||||||
monitor_operlog: () => import("@/views/monitor/operlog/index.vue"),
|
monitor_operlog: () => import("@/views/monitor/operlog/index.vue"),
|
||||||
|
"mps_import-heat": () => import("@/views/mps/import-heat/index.vue"),
|
||||||
"mps_manual-pricing": () => import("@/views/mps/manual-pricing/index.vue"),
|
"mps_manual-pricing": () => import("@/views/mps/manual-pricing/index.vue"),
|
||||||
"mps_market-yxzetgrb": () => import("@/views/mps/market-yxzetgrb/index.vue"),
|
"mps_market-yxzetgrb": () => import("@/views/mps/market-yxzetgrb/index.vue"),
|
||||||
mps_market: () => import("@/views/mps/market/index.vue"),
|
mps_market: () => import("@/views/mps/market/index.vue"),
|
||||||
|
@ -189,6 +189,15 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
i18nKey: 'route.mps'
|
i18nKey: 'route.mps'
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
name: 'mps_import-heat',
|
||||||
|
path: '/mps/import-heat',
|
||||||
|
component: 'view.mps_import-heat',
|
||||||
|
meta: {
|
||||||
|
title: 'mps_import-heat',
|
||||||
|
i18nKey: 'route.mps_import-heat'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'mps_manual-pricing',
|
name: 'mps_manual-pricing',
|
||||||
path: '/mps/manual-pricing',
|
path: '/mps/manual-pricing',
|
||||||
|
@ -185,6 +185,7 @@ const routeMap: RouteMap = {
|
|||||||
"monitor_online": "/monitor/online",
|
"monitor_online": "/monitor/online",
|
||||||
"monitor_operlog": "/monitor/operlog",
|
"monitor_operlog": "/monitor/operlog",
|
||||||
"mps": "/mps",
|
"mps": "/mps",
|
||||||
|
"mps_import-heat": "/mps/import-heat",
|
||||||
"mps_manual-pricing": "/mps/manual-pricing",
|
"mps_manual-pricing": "/mps/manual-pricing",
|
||||||
"mps_market": "/mps/market",
|
"mps_market": "/mps/market",
|
||||||
"mps_market-yxzetgrb": "/mps/market-yxzetgrb",
|
"mps_market-yxzetgrb": "/mps/market-yxzetgrb",
|
||||||
|
36
cds-fontend-2025.V1/src/service/api/mps/import-heat.ts
Normal file
36
cds-fontend-2025.V1/src/service/api/mps/import-heat.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { request } from '@/service/request';
|
||||||
|
|
||||||
|
/** 获取导入取暖费信息列表 */
|
||||||
|
export function fetchGetImportHeatList (params?: Api.Mps.ImportHeatSearchParams) {
|
||||||
|
return request<Api.Mps.ImportHeatList>({
|
||||||
|
url: '/mps/importHeat/list',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增导入取暖费信息 */
|
||||||
|
export function fetchCreateImportHeat (data: Api.Mps.ImportHeatOperateParams) {
|
||||||
|
return request<boolean>({
|
||||||
|
url: '/mps/importHeat',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改导入取暖费信息 */
|
||||||
|
export function fetchUpdateImportHeat (data: Api.Mps.ImportHeatOperateParams) {
|
||||||
|
return request<boolean>({
|
||||||
|
url: '/mps/importHeat',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 批量删除导入取暖费信息 */
|
||||||
|
export function fetchBatchDeleteImportHeat (ids: CommonType.IdType[]) {
|
||||||
|
return request<boolean>({
|
||||||
|
url: `/mps/importHeat/${ids.join(',')}`,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
}
|
77
cds-fontend-2025.V1/src/typings/api/mps.import-heat.api.d.ts
vendored
Normal file
77
cds-fontend-2025.V1/src/typings/api/mps.import-heat.api.d.ts
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* Namespace Api
|
||||||
|
*
|
||||||
|
* All backend api type
|
||||||
|
*/
|
||||||
|
declare namespace Api {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* namespace Mps
|
||||||
|
*
|
||||||
|
* backend api module: "Mps"
|
||||||
|
*/
|
||||||
|
namespace Mps {
|
||||||
|
/** import heat */
|
||||||
|
type ImportHeat = Common.CommonRecord<{
|
||||||
|
/** 主键 */
|
||||||
|
id: CommonType.IdType;
|
||||||
|
/** 用户编码 */
|
||||||
|
userCode: string;
|
||||||
|
/** 用户地址 */
|
||||||
|
userAddress: string;
|
||||||
|
/** 费用类别 */
|
||||||
|
feeType: string;
|
||||||
|
/** 缴费金额 */
|
||||||
|
paymentAmount: number;
|
||||||
|
/** 加热器金额 */
|
||||||
|
heaterAmount: number;
|
||||||
|
/** 缴费日期 */
|
||||||
|
paymentDate: string;
|
||||||
|
/** 流水号 */
|
||||||
|
transactionId: CommonType.IdType;
|
||||||
|
/** 订单状态 */
|
||||||
|
orderStatus: string;
|
||||||
|
/** 计价月份 */
|
||||||
|
importTime: string;
|
||||||
|
/** 租户编号 */
|
||||||
|
tenantId: CommonType.IdType;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
/** import heat search params */
|
||||||
|
type ImportHeatSearchParams = CommonType.RecordNullable<
|
||||||
|
Pick<
|
||||||
|
Api.Mps.ImportHeat,
|
||||||
|
| 'userCode'
|
||||||
|
| 'userAddress'
|
||||||
|
| 'feeType'
|
||||||
|
| 'paymentAmount'
|
||||||
|
| 'heaterAmount'
|
||||||
|
| 'paymentDate'
|
||||||
|
| 'transactionId'
|
||||||
|
| 'orderStatus'
|
||||||
|
| 'importTime'
|
||||||
|
> &
|
||||||
|
Api.Common.CommonSearchParams
|
||||||
|
>;
|
||||||
|
|
||||||
|
/** import heat operate params */
|
||||||
|
type ImportHeatOperateParams = CommonType.RecordNullable<
|
||||||
|
Pick<
|
||||||
|
Api.Mps.ImportHeat,
|
||||||
|
| 'userCode'
|
||||||
|
| 'userAddress'
|
||||||
|
| 'feeType'
|
||||||
|
| 'paymentAmount'
|
||||||
|
| 'heaterAmount'
|
||||||
|
| 'paymentDate'
|
||||||
|
| 'transactionId'
|
||||||
|
| 'orderStatus'
|
||||||
|
| 'importTime'
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
/** import heat list */
|
||||||
|
type ImportHeatList = Api.Common.PaginatingQueryRecord<ImportHeat>;
|
||||||
|
}
|
||||||
|
}
|
@ -39,6 +39,7 @@ declare module "@elegant-router/types" {
|
|||||||
"monitor_online": "/monitor/online";
|
"monitor_online": "/monitor/online";
|
||||||
"monitor_operlog": "/monitor/operlog";
|
"monitor_operlog": "/monitor/operlog";
|
||||||
"mps": "/mps";
|
"mps": "/mps";
|
||||||
|
"mps_import-heat": "/mps/import-heat";
|
||||||
"mps_manual-pricing": "/mps/manual-pricing";
|
"mps_manual-pricing": "/mps/manual-pricing";
|
||||||
"mps_market": "/mps/market";
|
"mps_market": "/mps/market";
|
||||||
"mps_market-yxzetgrb": "/mps/market-yxzetgrb";
|
"mps_market-yxzetgrb": "/mps/market-yxzetgrb";
|
||||||
@ -151,6 +152,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "monitor_logininfor"
|
| "monitor_logininfor"
|
||||||
| "monitor_online"
|
| "monitor_online"
|
||||||
| "monitor_operlog"
|
| "monitor_operlog"
|
||||||
|
| "mps_import-heat"
|
||||||
| "mps_manual-pricing"
|
| "mps_manual-pricing"
|
||||||
| "mps_market-yxzetgrb"
|
| "mps_market-yxzetgrb"
|
||||||
| "mps_market"
|
| "mps_market"
|
||||||
|
321
cds-fontend-2025.V1/src/views/mps/import-heat/index.vue
Normal file
321
cds-fontend-2025.V1/src/views/mps/import-heat/index.vue
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
<script setup lang="tsx">
|
||||||
|
import { NDivider } from 'naive-ui';
|
||||||
|
import { fetchBatchDeleteImportHeat, fetchGetImportHeatList } from '@/service/api/mps/import-heat';
|
||||||
|
import { useAppStore } from '@/store/modules/app';
|
||||||
|
import { useAuth } from '@/hooks/business/auth';
|
||||||
|
import { useDownload } from '@/hooks/business/download';
|
||||||
|
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
import ButtonIcon from '@/components/custom/button-icon.vue';
|
||||||
|
import ImportHeatOperateDrawer from './modules/import-heat-operate-drawer.vue';
|
||||||
|
import ImportHeatSearch from './modules/import-heat-search.vue';
|
||||||
|
import {computed, ref, watch} from "vue";
|
||||||
|
import {useBoolean} from "~/packages/hooks";
|
||||||
|
import ImportHeatImportModal from './modules/import-heat-import-modal.vue';
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
defineOptions({
|
||||||
|
name: 'ImportHeatList'
|
||||||
|
});
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const { download } = useDownload();
|
||||||
|
const { hasAuth } = useAuth();
|
||||||
|
const { bool: importVisible, setTrue: openImportModal } = useBoolean();
|
||||||
|
|
||||||
|
const {
|
||||||
|
columns,
|
||||||
|
columnChecks,
|
||||||
|
data,
|
||||||
|
getData,
|
||||||
|
getDataByPage,
|
||||||
|
loading,
|
||||||
|
mobilePagination,
|
||||||
|
searchParams,
|
||||||
|
resetSearchParams
|
||||||
|
} = useTable({
|
||||||
|
apiFn: fetchGetImportHeatList,
|
||||||
|
apiParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
// if you want to use the searchParams in Form, you need to define the following properties, and the value is null
|
||||||
|
// the value can not be undefined, otherwise the property in Form will not be reactive
|
||||||
|
userCode: null,
|
||||||
|
userAddress: null,
|
||||||
|
feeType: null,
|
||||||
|
paymentAmount: null,
|
||||||
|
heaterAmount: null,
|
||||||
|
paymentDate: null,
|
||||||
|
transactionId: null,
|
||||||
|
orderStatus: null,
|
||||||
|
importTime: null,
|
||||||
|
params: {}
|
||||||
|
},
|
||||||
|
columns: () => [
|
||||||
|
{
|
||||||
|
type: 'selection',
|
||||||
|
align: 'center',
|
||||||
|
width: 48
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'index',
|
||||||
|
title: $t('common.index'),
|
||||||
|
align: 'center',
|
||||||
|
width: 64,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// key: 'id',
|
||||||
|
// title: '主键',
|
||||||
|
// align: 'center',
|
||||||
|
// minWidth: 120,
|
||||||
|
// ellipsis: true,
|
||||||
|
// resizable: true,
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
key: 'userCode',
|
||||||
|
title: '用户编码',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'userAddress',
|
||||||
|
title: '用户地址',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'feeType',
|
||||||
|
title: '费用类别',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'paymentAmount',
|
||||||
|
title: '缴费金额',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'heaterAmount',
|
||||||
|
title: '加热器金额',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'paymentDate',
|
||||||
|
title: '缴费日期',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'transactionId',
|
||||||
|
title: '流水号',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'orderStatus',
|
||||||
|
title: '订单状态',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'importTime',
|
||||||
|
title: '计价月份',
|
||||||
|
align: 'center',
|
||||||
|
minWidth: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
resizable: true,
|
||||||
|
slots: {
|
||||||
|
default: ({ row }) => {
|
||||||
|
return dayjs(row.importTime).format('YYYY-MM');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'operate',
|
||||||
|
title: $t('common.operate'),
|
||||||
|
fixed: 'right',
|
||||||
|
width: 130,
|
||||||
|
render: row => {
|
||||||
|
const divider = () => {
|
||||||
|
if (!hasAuth('mps:importHeat:edit') || !hasAuth('mps:importHeat:remove')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <NDivider vertical />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const editBtn = () => {
|
||||||
|
if (!hasAuth('mps:importHeat:edit')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ButtonIcon
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
icon="material-symbols:drive-file-rename-outline-outline"
|
||||||
|
tooltipContent={$t('common.edit')}
|
||||||
|
onClick={() => edit(row.id!)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteBtn = () => {
|
||||||
|
if (!hasAuth('mps:importHeat:remove')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ButtonIcon
|
||||||
|
text
|
||||||
|
type="error"
|
||||||
|
icon="material-symbols:delete-outline"
|
||||||
|
tooltipContent={$t('common.delete')}
|
||||||
|
popconfirmContent={$t('common.confirmDelete')}
|
||||||
|
onPositiveClick={() => handleDelete(row.id!)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="flex-center gap-8px">
|
||||||
|
|
||||||
|
{deleteBtn()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const scrollX = ref(0);
|
||||||
|
// 计算总宽度函数
|
||||||
|
const calculateTotalWidth = () => {
|
||||||
|
let totalWidth = 0;
|
||||||
|
const visibleColumns = columns.value;
|
||||||
|
for (let i = 0; i < visibleColumns.length; i++) {
|
||||||
|
const column = visibleColumns[i];
|
||||||
|
// 获取列的实际渲染宽度
|
||||||
|
// 注意:调整大小时会更新 column.width
|
||||||
|
let width = column.width;
|
||||||
|
// 如果没有显式宽度,则使用minWidth或默认值
|
||||||
|
if (!width) {
|
||||||
|
width = column.minWidth || 120;
|
||||||
|
}
|
||||||
|
// 转换为数字类型
|
||||||
|
width = typeof width === 'string' ? parseInt(width) : width;
|
||||||
|
totalWidth += width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加额外的50px余量防止边缘裁剪
|
||||||
|
return totalWidth + 50;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听列变化并计算宽度
|
||||||
|
watch(columns, (newColumns) => {
|
||||||
|
scrollX.value = calculateTotalWidth();
|
||||||
|
}, { deep: true });
|
||||||
|
|
||||||
|
|
||||||
|
const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
|
||||||
|
useTableOperate(data, getData);
|
||||||
|
|
||||||
|
async function handleBatchDelete() {
|
||||||
|
// request
|
||||||
|
const { error } = await fetchBatchDeleteImportHeat(checkedRowKeys.value);
|
||||||
|
if (error) return;
|
||||||
|
onBatchDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete(id: CommonType.IdType) {
|
||||||
|
// request
|
||||||
|
const { error } = await fetchBatchDeleteImportHeat([id]);
|
||||||
|
if (error) return;
|
||||||
|
onDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
function edit(id: CommonType.IdType) {
|
||||||
|
handleEdit('id', id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleImport() {
|
||||||
|
openImportModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleExport() {
|
||||||
|
download('/mps/importHeat/export', searchParams, `导入取暖费信息_${new Date().getTime()}.xlsx`);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
||||||
|
<ImportHeatSearch v-model:model="searchParams" @reset="resetSearchParams" @search="getDataByPage" />
|
||||||
|
<NCard title="取暖费信息列表" :bordered="false" size="small" class="sm:flex-1-hidden card-wrapper">
|
||||||
|
<template #header-extra>
|
||||||
|
<TableHeaderOperation
|
||||||
|
v-model:columns="columnChecks"
|
||||||
|
:disabled-delete="checkedRowKeys.length === 0"
|
||||||
|
:loading="loading"
|
||||||
|
:show-add="hasAuth('mps:importHeat:add')"
|
||||||
|
:show-delete="hasAuth('mps:importHeat:remove')"
|
||||||
|
:show-export="hasAuth('mps:importHeat:export')"
|
||||||
|
@add="handleAdd"
|
||||||
|
@delete="handleBatchDelete"
|
||||||
|
@export="handleExport"
|
||||||
|
@refresh="getData"
|
||||||
|
>
|
||||||
|
<template #after>
|
||||||
|
<NButton v-if="hasAuth('mps:privateEbankNew:export')" size="small" ghost @click="handleImport">
|
||||||
|
<template #icon>
|
||||||
|
<icon-material-symbols:upload-rounded class="text-icon"/>
|
||||||
|
</template>
|
||||||
|
{{ $t('common.import') }}
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
</TableHeaderOperation>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!--scroll-x : 所有表格列宽度之和(包含操作列)+操作列宽度-->
|
||||||
|
<NDataTable
|
||||||
|
v-model:checked-row-keys="checkedRowKeys"
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
size="small"
|
||||||
|
:flex-height="!appStore.isMobile"
|
||||||
|
:scroll-x="scrollX"
|
||||||
|
:loading="loading"
|
||||||
|
remote
|
||||||
|
:row-key="row => row.id"
|
||||||
|
:pagination="mobilePagination"
|
||||||
|
class="sm:h-full"
|
||||||
|
@update-resize-widths="scrollX = calculateTotalWidth()"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImportHeatImportModal v-model:visible="importVisible" @submitted="getDataByPage"/>
|
||||||
|
|
||||||
|
<ImportHeatOperateDrawer
|
||||||
|
v-model:visible="drawerVisible"
|
||||||
|
:operate-type="operateType"
|
||||||
|
:row-data="editingData"
|
||||||
|
@submitted="getDataByPage"
|
||||||
|
/>
|
||||||
|
</NCard>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@ -0,0 +1,176 @@
|
|||||||
|
[[[
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { h, ref, watch } from 'vue';
|
||||||
|
import type { UploadFileInfo } from 'naive-ui';
|
||||||
|
import { getToken } from '@/store/modules/auth/shared';
|
||||||
|
import { useDownload } from '@/hooks/business/download';
|
||||||
|
import { getServiceBaseURL } from '@/utils/service';
|
||||||
|
import type FileUpload from '@/components/custom/file-upload.vue';
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ImportHeatImportModal'
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'submitted'): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { download } = useDownload();
|
||||||
|
|
||||||
|
const { baseURL } = getServiceBaseURL(import.meta.env);
|
||||||
|
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
Authorization: `Bearer ${ getToken() }`,
|
||||||
|
clientid: import.meta.env.VITE_APP_CLIENT_ID!
|
||||||
|
};
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const uploadRef = ref<typeof FileUpload>();
|
||||||
|
const message = ref<string>('');
|
||||||
|
const success = ref<boolean>(false);
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', {
|
||||||
|
default: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = ref<Record<string, any>>({
|
||||||
|
updateSupport: false,
|
||||||
|
// importMonth: dayjs().subtract(1, 'month').startOf('month').utc().toISOString()
|
||||||
|
importMonth:new Date(dayjs().subtract(1, 'month').format('YYYY-MM')).toISOString()
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const fileList = ref<UploadFileInfo[]>([]);
|
||||||
|
|
||||||
|
function closeDrawer() {
|
||||||
|
visible.value = false;
|
||||||
|
if (success.value) {
|
||||||
|
emit('submitted');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSubmit() {
|
||||||
|
fileList.value.forEach(item => {
|
||||||
|
item.status = 'pending';
|
||||||
|
});
|
||||||
|
uploadRef.value?.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isErrorState(xhr: XMLHttpRequest) {
|
||||||
|
const responseText = xhr?.responseText;
|
||||||
|
const response = JSON.parse(responseText);
|
||||||
|
return response.code !== 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFinish(options: { file: UploadFileInfo; event?: ProgressEvent }) {
|
||||||
|
const { file, event } = options;
|
||||||
|
// @ts-expect-error Ignore type errors
|
||||||
|
const responseText = event?.target?.responseText;
|
||||||
|
const response = JSON.parse(responseText);
|
||||||
|
message.value = response.msg;
|
||||||
|
window.$message?.success($t('common.importSuccess'));
|
||||||
|
success.value = true;
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(options: { file: UploadFileInfo; event?: ProgressEvent }) {
|
||||||
|
const { event } = options;
|
||||||
|
// @ts-expect-error Ignore type errors
|
||||||
|
const responseText = event?.target?.responseText;
|
||||||
|
const msg = JSON.parse(responseText).msg;
|
||||||
|
message.value = msg;
|
||||||
|
window.$message?.error(() => h('div', { innerHTML: msg || $t('common.importFail') }));
|
||||||
|
success.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDownloadTemplate() {
|
||||||
|
download(
|
||||||
|
'/mps/importHeat/importTemplate',
|
||||||
|
{},
|
||||||
|
`${ $t('mps.common') }_${ $t('common.importTemplate') }_${ new Date().getTime() }.xlsx`
|
||||||
|
);
|
||||||
|
closeDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(visible, () => {
|
||||||
|
if (visible.value) {
|
||||||
|
fileList.value = [];
|
||||||
|
success.value = false;
|
||||||
|
message.value = '';
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
</script>
|
||||||
|
]]]
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NModal
|
||||||
|
v-model:show="visible"
|
||||||
|
:title="$t('common.import')"
|
||||||
|
preset="card"
|
||||||
|
:bordered="false"
|
||||||
|
display-directive="show"
|
||||||
|
class="max-w-90% w-600px"
|
||||||
|
@close="closeDrawer"
|
||||||
|
>
|
||||||
|
<NUpload
|
||||||
|
ref="uploadRef"
|
||||||
|
v-model:file-list="fileList"
|
||||||
|
:action="`${baseURL}/mps/importHeat/importData`"
|
||||||
|
:headers="headers"
|
||||||
|
:data="data"
|
||||||
|
:max="1"
|
||||||
|
:file-size="50"
|
||||||
|
accept=".xls,.xlsx"
|
||||||
|
:multiple="false"
|
||||||
|
directory-dnd
|
||||||
|
:default-upload="false"
|
||||||
|
list-type="text"
|
||||||
|
:is-error-state="isErrorState"
|
||||||
|
@finish="handleFinish"
|
||||||
|
@error="handleError"
|
||||||
|
>
|
||||||
|
<NUploadDragger>
|
||||||
|
<div class="mb-12px flex-left">
|
||||||
|
<SvgIcon icon="material-symbols:unarchive-outline" class="text-58px color-#d8d8db dark:color-#a1a1a2" />
|
||||||
|
</div>
|
||||||
|
<NText class="text-16px">{{ $t('common.importTip') }}</NText>
|
||||||
|
<NP depth="3" class="mt-8px text-center">
|
||||||
|
{{ $t('common.importSize') }}
|
||||||
|
<b class="text-red-500">50MB</b>
|
||||||
|
{{ $t('common.importFormat') }}
|
||||||
|
<b class="text-red-500">xls/xlsx</b>
|
||||||
|
{{ $t('common.importEnd') }}
|
||||||
|
</NP>
|
||||||
|
</NUploadDragger>
|
||||||
|
</NUpload>
|
||||||
|
<div class="flex-center">
|
||||||
|
<NCheckbox v-model="data.updateSupport">{{ $t('common.updateExisting') }}</NCheckbox>
|
||||||
|
<n-divider vertical />
|
||||||
|
<NDatePicker
|
||||||
|
v-model:value="data.importMonth"
|
||||||
|
type="month"
|
||||||
|
:format="'YYYY-MM'"
|
||||||
|
default-time="08:00:00"
|
||||||
|
:value-format="'YYYY-MM'"
|
||||||
|
:placeholder="$t('common.selectImportMonth')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<NAlert v-if="message" :title="$t('common.importResult')" :type="success ? 'success' : 'error'" :bordered="false">
|
||||||
|
<template #default>
|
||||||
|
<div v-html="message"></div>
|
||||||
|
</template>
|
||||||
|
</NAlert>
|
||||||
|
<template #footer>
|
||||||
|
<NSpace justify="end" :size="16">
|
||||||
|
<NButton @click="handleDownloadTemplate">{{ $t('common.downloadTemplate') }}</NButton>
|
||||||
|
<NButton type="primary" @click="handleSubmit">{{ $t('common.import') }}</NButton>
|
||||||
|
</NSpace>
|
||||||
|
</template>
|
||||||
|
</NModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@ -0,0 +1,179 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, reactive, watch } from 'vue';
|
||||||
|
import { fetchCreateImportHeat, fetchUpdateImportHeat } from '@/service/api/mps/import-heat';
|
||||||
|
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ImportHeatOperateDrawer'
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** the type of operation */
|
||||||
|
operateType: NaiveUI.TableOperateType;
|
||||||
|
/** the edit row data */
|
||||||
|
rowData?: Api.Mps.ImportHeat | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'submitted'): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', {
|
||||||
|
default: false
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const { formRef, validate, restoreValidation } = useNaiveForm();
|
||||||
|
const { createRequiredRule } = useFormRules();
|
||||||
|
|
||||||
|
const title = computed(() => {
|
||||||
|
const titles: Record<NaiveUI.TableOperateType, string> = {
|
||||||
|
add: '新增取暖费信息',
|
||||||
|
edit: '编辑取暖费信息'
|
||||||
|
};
|
||||||
|
return titles[props.operateType];
|
||||||
|
});
|
||||||
|
|
||||||
|
type Model = Api.Mps.ImportHeatOperateParams;
|
||||||
|
|
||||||
|
const model: Model = reactive(createDefaultModel());
|
||||||
|
|
||||||
|
function createDefaultModel(): Model {
|
||||||
|
return {
|
||||||
|
userCode: '',
|
||||||
|
userAddress: '',
|
||||||
|
feeType: '',
|
||||||
|
paymentAmount: undefined,
|
||||||
|
heaterAmount: undefined,
|
||||||
|
paymentDate: undefined,
|
||||||
|
transactionId: '',
|
||||||
|
orderStatus: '',
|
||||||
|
importTime: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type RuleKey = Extract<
|
||||||
|
keyof Model,
|
||||||
|
| 'userCode'
|
||||||
|
| 'importTime'
|
||||||
|
| 'tenantId'
|
||||||
|
| 'createDept'
|
||||||
|
| 'createBy'
|
||||||
|
| 'createTime'
|
||||||
|
| 'updateBy'
|
||||||
|
| 'updateTime'
|
||||||
|
>;
|
||||||
|
|
||||||
|
const rules: Record<RuleKey, App.Global.FormRule> = {
|
||||||
|
userCode: createRequiredRule('用户编码不能为空'),
|
||||||
|
importTime: createRequiredRule('计价月份不能为空'),
|
||||||
|
tenantId: createRequiredRule('租户编号不能为空'),
|
||||||
|
createDept: createRequiredRule('创建部门不能为空'),
|
||||||
|
createBy: createRequiredRule('创建者不能为空'),
|
||||||
|
createTime: createRequiredRule('创建时间不能为空'),
|
||||||
|
updateBy: createRequiredRule('更新者不能为空'),
|
||||||
|
updateTime: createRequiredRule('更新时间不能为空')
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleUpdateModelWhenEdit() {
|
||||||
|
if (props.operateType === 'add') {
|
||||||
|
Object.assign(model, createDefaultModel());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.operateType === 'edit' && props.rowData) {
|
||||||
|
Object.assign(model, props.rowData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDrawer() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSubmit() {
|
||||||
|
await validate();
|
||||||
|
|
||||||
|
const { userCode, userAddress, feeType, paymentAmount, heaterAmount, paymentDate, transactionId, orderStatus, importTime } = model;
|
||||||
|
|
||||||
|
// request
|
||||||
|
if (props.operateType === 'add') {
|
||||||
|
const { error } = await fetchCreateImportHeat({ userCode, userAddress, feeType, paymentAmount, heaterAmount, paymentDate, transactionId, orderStatus, importTime });
|
||||||
|
if (error) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.operateType === 'edit') {
|
||||||
|
const { error } = await fetchUpdateImportHeat({ });
|
||||||
|
if (error) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.$message?.success($t('common.updateSuccess'));
|
||||||
|
closeDrawer();
|
||||||
|
emit('submitted');
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(visible, () => {
|
||||||
|
if (visible.value) {
|
||||||
|
handleUpdateModelWhenEdit();
|
||||||
|
restoreValidation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
|
||||||
|
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
||||||
|
<NForm ref="formRef" :model="model" :rules="rules">
|
||||||
|
<NFormItem label="用户编码" path="userCode">
|
||||||
|
<NInput v-model:value="model.userCode" placeholder="请输入用户编码" />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="用户地址" path="userAddress">
|
||||||
|
<NInput v-model:value="model.userAddress" placeholder="请输入用户地址" />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="费用类别" path="feeType">
|
||||||
|
<NInput v-model:value="model.feeType" placeholder="请输入费用类别" />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="缴费金额" path="paymentAmount">
|
||||||
|
<NInput v-model:value="model.paymentAmount" placeholder="请输入缴费金额" />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="加热器金额" path="heaterAmount">
|
||||||
|
<NInput v-model:value="model.heaterAmount" placeholder="请输入加热器金额" />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="缴费日期" path="paymentDate">
|
||||||
|
<NDatePicker
|
||||||
|
v-model:formatted-value="model.paymentDate"
|
||||||
|
type="datetime"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="流水号" path="transactionId">
|
||||||
|
<NInput v-model:value="model.transactionId" placeholder="请输入流水号" />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="订单状态" path="orderStatus">
|
||||||
|
<NInput v-model:value="model.orderStatus" placeholder="请输入订单状态" />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="计价月份" path="importTime">
|
||||||
|
<NDatePicker
|
||||||
|
v-model:formatted-value="model.importTime"
|
||||||
|
type="month"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
</NForm>
|
||||||
|
<template #footer>
|
||||||
|
<NSpace :size="16">
|
||||||
|
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
||||||
|
<NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
|
||||||
|
</NSpace>
|
||||||
|
</template>
|
||||||
|
</NDrawerContent>
|
||||||
|
</NDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
@ -0,0 +1,106 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useNaiveForm } from '@/hooks/common/form';
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ImportHeatSearch'
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'reset'): void;
|
||||||
|
(e: 'search'): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const { formRef, validate, restoreValidation } = useNaiveForm();
|
||||||
|
|
||||||
|
|
||||||
|
const model = defineModel<Api.Mps.ImportHeatSearchParams>('model', { required: true });
|
||||||
|
|
||||||
|
|
||||||
|
async function reset() {
|
||||||
|
Object.assign(model.value.params!, {});
|
||||||
|
await restoreValidation();
|
||||||
|
emit('reset');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function search() {
|
||||||
|
await validate();
|
||||||
|
emit('search');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NCard :bordered="false" size="small" class="card-wrapper">
|
||||||
|
<NCollapse>
|
||||||
|
<NCollapseItem :title="$t('common.search')" name="user-search">
|
||||||
|
<NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
|
||||||
|
<NGrid responsive="screen" item-responsive>
|
||||||
|
<NFormItemGi span="24 s:12 m:6" label="用户编码" path="userCode" class="pr-24px">
|
||||||
|
<NInput v-model:value="model.userCode" placeholder="请输入用户编码" />
|
||||||
|
</NFormItemGi>
|
||||||
|
<!-- <NFormItemGi span="24 s:12 m:6" label="用户地址" path="userAddress" class="pr-24px">-->
|
||||||
|
<!-- <NInput v-model:value="model.userAddress" placeholder="请输入用户地址" />-->
|
||||||
|
<!-- </NFormItemGi>-->
|
||||||
|
<!-- <NFormItemGi span="24 s:12 m:6" label="费用类别" path="feeType" class="pr-24px">-->
|
||||||
|
<!-- <NSelect-->
|
||||||
|
<!-- v-model:value="model.feeType"-->
|
||||||
|
<!-- placeholder="请选择费用类别"-->
|
||||||
|
<!-- :options="[]"-->
|
||||||
|
<!-- clearable-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </NFormItemGi>-->
|
||||||
|
<!-- <NFormItemGi span="24 s:12 m:6" label="缴费金额" path="paymentAmount" class="pr-24px">-->
|
||||||
|
<!-- <NInput v-model:value="model.paymentAmount" placeholder="请输入缴费金额" />-->
|
||||||
|
<!-- </NFormItemGi>-->
|
||||||
|
<!-- <NFormItemGi span="24 s:12 m:6" label="加热器金额" path="heaterAmount" class="pr-24px">-->
|
||||||
|
<!-- <NInput v-model:value="model.heaterAmount" placeholder="请输入加热器金额" />-->
|
||||||
|
<!-- </NFormItemGi>-->
|
||||||
|
<!-- <NFormItemGi span="24 s:12 m:6" label="缴费日期" path="paymentDate" class="pr-24px">-->
|
||||||
|
<!-- <NDatePicker-->
|
||||||
|
<!-- v-model:formatted-value="model.paymentDate"-->
|
||||||
|
<!-- type="datetime"-->
|
||||||
|
<!-- value-format="yyyy-MM-dd HH:mm:ss"-->
|
||||||
|
<!-- clearable-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </NFormItemGi>-->
|
||||||
|
<!-- <NFormItemGi span="24 s:12 m:6" label="流水号" path="transactionId" class="pr-24px">-->
|
||||||
|
<!-- <NInput v-model:value="model.transactionId" placeholder="请输入流水号" />-->
|
||||||
|
<!-- </NFormItemGi>-->
|
||||||
|
<!-- <NFormItemGi span="24 s:12 m:6" label="订单状态" path="orderStatus" class="pr-24px">-->
|
||||||
|
<!-- <NInput v-model:value="model.orderStatus" placeholder="请输入订单状态" />-->
|
||||||
|
<!-- </NFormItemGi>-->
|
||||||
|
<NFormItemGi span="24 s:12 m:6" label="计价月份" path="importTime" class="pr-24px">
|
||||||
|
<NDatePicker
|
||||||
|
v-model:formatted-value="model.importTime"
|
||||||
|
type="month"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</NFormItemGi>
|
||||||
|
<NFormItemGi span="24" class="pr-24px">
|
||||||
|
<NSpace class="w-full" justify="end">
|
||||||
|
<NButton @click="reset">
|
||||||
|
<template #icon>
|
||||||
|
<icon-ic-round-refresh class="text-icon" />
|
||||||
|
</template>
|
||||||
|
{{ $t('common.reset') }}
|
||||||
|
</NButton>
|
||||||
|
<NButton type="primary" ghost @click="search">
|
||||||
|
<template #icon>
|
||||||
|
<icon-ic-round-search class="text-icon" />
|
||||||
|
</template>
|
||||||
|
{{ $t('common.search') }}
|
||||||
|
</NButton>
|
||||||
|
</NSpace>
|
||||||
|
</NFormItemGi>
|
||||||
|
</NGrid>
|
||||||
|
</NForm>
|
||||||
|
</NCollapseItem>
|
||||||
|
</NCollapse>
|
||||||
|
</NCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
Loading…
Reference in New Issue
Block a user