第二阶段代码
This commit is contained in:
345
apps/web-ele/src/views/database/info/add/index.vue
Normal file
345
apps/web-ele/src/views/database/info/add/index.vue
Normal file
@@ -0,0 +1,345 @@
|
||||
<script setup lang="ts">
|
||||
import { createResourceBatch, getInfoPriceBook } from '#/api/database/info';
|
||||
import { DbHst } from '#/components/db-hst';
|
||||
import { DbTree } from '#/components/db-tree';
|
||||
import { useUpload } from '#/components/upload/use-upload';
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
import { useElementSize } from '@vueuse/core';
|
||||
import type { UploadProps } from 'element-plus';
|
||||
import { ElButton, ElCard, ElDialog, ElImage, ElInput, ElMessage, ElSplitter, ElSplitterPanel, ElText, ElUpload } from 'element-plus';
|
||||
import { computed, nextTick, onMounted, ref } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { HistoryDialog } from '../components/history-dialog';
|
||||
import { MorePriceDialog } from '../components/more-price-dialog';
|
||||
import { useDbHst } from './dbHst';
|
||||
import { useDbTree } from './dbTree';
|
||||
|
||||
const route = useRoute();
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
const { uploadUrl, httpRequest } = useUpload('info-price');
|
||||
|
||||
const bookId = ref<any>(null);
|
||||
const currentCategoryTreeId = ref<any>(null);
|
||||
const bookTitle = ref<string>('');
|
||||
const bookInfo = ref<any>(null);
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null);
|
||||
const { height: containerHeight } = useElementSize(containerRef);
|
||||
|
||||
const isCcompleted = computed(() => accessStore.tenantId != 1 && bookInfo.value?.publishStatus === 'completed');
|
||||
|
||||
const dbTreeRef = ref();
|
||||
const hstRef = ref();
|
||||
|
||||
const previewImageUrl = ref<string>('');
|
||||
const previewVisible = ref(false);
|
||||
const uploadDialogVisible = ref(false);
|
||||
const currentUploadRow = ref<number>(0);
|
||||
const currentUploadCol = ref<number>(0);
|
||||
const uploadImageUrl = ref<string>('');
|
||||
const uploading = ref(false);
|
||||
|
||||
const morePriceDialogVisible = ref(false);
|
||||
const currentPriceRow = ref<number>(0);
|
||||
const selectRowPrice = ref<any>(null);
|
||||
|
||||
const historyDialogVisible = ref(false);
|
||||
const categorySource = ref<{ label: string; value: any }[]>([]);
|
||||
const search = ref();
|
||||
|
||||
const handlePhotoPreview = (value: string) => {
|
||||
previewImageUrl.value = value;
|
||||
previewVisible.value = true;
|
||||
};
|
||||
|
||||
const handlePhotoUpload = (row: number, col: number, value: string) => {
|
||||
currentUploadRow.value = row;
|
||||
currentUploadCol.value = col;
|
||||
uploadImageUrl.value = value;
|
||||
uploadDialogVisible.value = true;
|
||||
};
|
||||
|
||||
const handleShowMorePrice = (row: number, col: number, value: any) => {
|
||||
currentPriceRow.value = row;
|
||||
morePriceDialogVisible.value = true;
|
||||
selectRowPrice.value = hstRef.value.hotInstance.getSourceDataAtRow(row);
|
||||
console.log('查看更多单价:', { row, col, value }, selectRowPrice.value);
|
||||
};
|
||||
|
||||
const callbacks = {
|
||||
onPhotoPreview: handlePhotoPreview,
|
||||
onPhotoUpload: handlePhotoUpload,
|
||||
onShowMorePrice: handleShowMorePrice,
|
||||
};
|
||||
|
||||
const {
|
||||
columns,
|
||||
contextMenuItems,
|
||||
dbSettings,
|
||||
loadResourcePage,
|
||||
loadCategorySource,
|
||||
updateCategoryColumnSource,
|
||||
} = useDbHst(hstRef, bookId, currentCategoryTreeId, isCcompleted, callbacks);
|
||||
|
||||
const {
|
||||
treeData,
|
||||
rootMenus,
|
||||
nodeMenus,
|
||||
loadCategoryTree,
|
||||
handleTreeNodeSelect,
|
||||
handleTreeNodeEdit,
|
||||
} = useDbTree(dbTreeRef, bookId, isCcompleted, currentCategoryTreeId, loadResourcePage);
|
||||
|
||||
const loadBookInfo = async () => {
|
||||
if (!bookId.value) return;
|
||||
|
||||
try {
|
||||
const res = await getInfoPriceBook(bookId.value);
|
||||
if (res) {
|
||||
bookInfo.value = res;
|
||||
bookTitle.value = `${res.name} (${res.startTime} ~ ${res.endTime})`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载信息价册失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectPrice = async (row: any) => {
|
||||
if (hstRef.value?.hotInstance && selectRowPrice.value) {
|
||||
const sendData = {
|
||||
...selectRowPrice.value,
|
||||
priceTaxExcl: row.priceTaxExcl,
|
||||
taxRate: row.taxRate,
|
||||
priceTaxIncl: row.priceTaxIncl,
|
||||
};
|
||||
|
||||
try {
|
||||
await createResourceBatch([sendData]);
|
||||
ElMessage.success('更新成功');
|
||||
loadResourcePage();
|
||||
} catch (error) {
|
||||
console.error('更新失败:', error);
|
||||
ElMessage.error('更新失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleHistoryConfirm = async (nodes: any[]) => {
|
||||
if (!nodes || nodes.length === 0) {
|
||||
ElMessage.warning('请选择要导入的数据');
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedNodes = nodes.map(node => ({
|
||||
...node,
|
||||
categoryTreeId: currentCategoryTreeId.value,
|
||||
resourceItemId: node.id,
|
||||
id: null,
|
||||
}));
|
||||
|
||||
const res = await createResourceBatch(updatedNodes);
|
||||
if (hstRef.value?.hotInstance && res) {
|
||||
loadResourcePage();
|
||||
ElMessage.success(`成功导入 ${updatedNodes.length} 条数据`);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBeforeUpload: UploadProps['beforeUpload'] = rawFile => {
|
||||
if (!rawFile.type.startsWith('image/')) {
|
||||
ElMessage.error('只能上传图片文件!');
|
||||
return false;
|
||||
}
|
||||
if (rawFile.size / 1024 / 1024 > 5) {
|
||||
ElMessage.error('图片大小不能超过 5MB!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleHttpRequest = (options: any) => {
|
||||
uploading.value = true;
|
||||
return httpRequest(options.file);
|
||||
};
|
||||
|
||||
const handleUploadSuccess: UploadProps['onSuccess'] = (response: any) => {
|
||||
uploading.value = false;
|
||||
const imageUrl = response?.url || response;
|
||||
uploadImageUrl.value = imageUrl;
|
||||
|
||||
if (hstRef.value?.hotInstance) {
|
||||
hstRef.value.hotInstance.setDataAtCell(currentUploadRow.value, currentUploadCol.value, imageUrl);
|
||||
}
|
||||
ElMessage.success('上传成功');
|
||||
handleDialogClose();
|
||||
};
|
||||
|
||||
const handleUploadError: UploadProps['onError'] = () => {
|
||||
uploading.value = false;
|
||||
ElMessage.error('上传失败,请重试');
|
||||
};
|
||||
|
||||
const handleUploadChange: UploadProps['onChange'] = uploadFile => {
|
||||
if (uploadFile.raw) {
|
||||
uploadImageUrl.value = URL.createObjectURL(uploadFile.raw);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDialogClose = () => {
|
||||
uploadDialogVisible.value = false;
|
||||
};
|
||||
|
||||
const handlePreviewClose = () => {
|
||||
previewVisible.value = false;
|
||||
previewImageUrl.value = '';
|
||||
};
|
||||
|
||||
const handleQuery = () => {
|
||||
console.log('handleQuery');
|
||||
};
|
||||
|
||||
const handleOpenHistoryDialog = () => {
|
||||
if (!currentCategoryTreeId.value) {
|
||||
ElMessage.warning('请先选择左侧分类节点');
|
||||
return;
|
||||
}
|
||||
historyDialogVisible.value = true;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
bookId.value = route.params.id || route.query.id;
|
||||
await loadBookInfo();
|
||||
await loadCategoryTree();
|
||||
categorySource.value = await loadCategorySource();
|
||||
updateCategoryColumnSource(categorySource.value);
|
||||
|
||||
nextTick(() => {
|
||||
if (hstRef.value?.hotInstance) {
|
||||
if (accessStore.tenantId != 1) {
|
||||
const editableColumns = ['priceTaxExcl', 'taxRate', 'priceTaxIncl'];
|
||||
const updatedColumns = columns.map(col => ({
|
||||
...col,
|
||||
editor: editableColumns.includes(col.data) ? col.editor : false,
|
||||
}));
|
||||
hstRef.value.hotInstance.updateSettings({
|
||||
columns: updatedColumns,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<ElCard class="h-full w-full border-radius-0" body-class="!p-0 h-full w-full flex flex-col" header-class="!p-1">
|
||||
<div class="!p-1">
|
||||
<ElText class="mx-1">信息价名称: {{ bookTitle }}</ElText>
|
||||
<ElInput
|
||||
v-model="search"
|
||||
style="width: 300px"
|
||||
placeholder="请输入"
|
||||
class="input-with-select"
|
||||
size="small"
|
||||
>
|
||||
<template #append>
|
||||
<ElButton @click="handleQuery" size="small"><IconifyIcon icon="ep:search" /></ElButton>
|
||||
</template>
|
||||
</ElInput>
|
||||
<ElButton
|
||||
@click="handleOpenHistoryDialog"
|
||||
type="primary"
|
||||
size="small"
|
||||
style="float: right"
|
||||
:disabled="isCcompleted"
|
||||
>
|
||||
调用历史信息
|
||||
</ElButton>
|
||||
</div>
|
||||
<div class="h-full w-full" ref="containerRef">
|
||||
<ElSplitter :style="{ height: containerHeight + 'px' }">
|
||||
<ElSplitterPanel size="15%" :min="200">
|
||||
<ElCard class="w-full h-full border-radius-0" body-class="!p-0 h-full w-full flex flex-col">
|
||||
<DbTree
|
||||
ref="dbTreeRef"
|
||||
:tree-data="treeData"
|
||||
:root-menus="rootMenus"
|
||||
:node-menus="nodeMenus"
|
||||
@node-edit="handleTreeNodeEdit"
|
||||
@node-click="handleTreeNodeSelect"
|
||||
:defaultExpandedLevel="4"
|
||||
/>
|
||||
</ElCard>
|
||||
</ElSplitterPanel>
|
||||
<ElSplitterPanel :min="200">
|
||||
<ElCard class="w-full h-full border-radius-0" body-class="!p-0 h-full w-full flex flex-col">
|
||||
<DbHst ref="hstRef" :settings="dbSettings" :contextMenuItems="contextMenuItems" />
|
||||
</ElCard>
|
||||
</ElSplitterPanel>
|
||||
</ElSplitter>
|
||||
</div>
|
||||
</ElCard>
|
||||
|
||||
<HistoryDialog
|
||||
v-model:visible="historyDialogVisible"
|
||||
:bookInfo="bookInfo"
|
||||
:categorySource="categorySource"
|
||||
@confirm="handleHistoryConfirm"
|
||||
/>
|
||||
|
||||
<ElDialog v-model="uploadDialogVisible" title="上传图片" width="500px" @close="handleDialogClose">
|
||||
<div class="upload-container">
|
||||
<ElUpload
|
||||
class="upload-demo"
|
||||
drag
|
||||
:action="uploadUrl"
|
||||
:http-request="handleHttpRequest"
|
||||
:show-file-list="false"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleUploadError"
|
||||
:on-change="handleUploadChange"
|
||||
accept="image/*"
|
||||
:disabled="uploading"
|
||||
>
|
||||
<div class="flex min-h-[200px] flex-col items-center justify-center py-8">
|
||||
<span class="icon-[mdi--cloud-upload-outline] mb-4 text-6xl text-gray-400"></span>
|
||||
<div class="text-base text-gray-600">点击或拖拽文件到此区域上传</div>
|
||||
<div class="mt-2 text-sm text-gray-400">支持 .jpg、.png、.gif、.webp 格式图片文件</div>
|
||||
</div>
|
||||
</ElUpload>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<ElButton @click="handleDialogClose" :disabled="uploading">关闭</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
|
||||
<ElDialog v-model="previewVisible" title="图片预览" width="800px" @close="handlePreviewClose">
|
||||
<div class="preview-image-container">
|
||||
<ElImage
|
||||
:src="previewImageUrl"
|
||||
fit="contain"
|
||||
:preview-src-list="[previewImageUrl]"
|
||||
:initial-index="0"
|
||||
style="width: 100%; max-height: 600px"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<ElButton @click="handlePreviewClose">关闭</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
|
||||
<MorePriceDialog
|
||||
v-model:visible="morePriceDialogVisible"
|
||||
:bookInfo="bookInfo"
|
||||
:selectRowPrice="selectRowPrice"
|
||||
@select="handleSelectPrice"
|
||||
/>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style lang="css"></style>
|
||||
Reference in New Issue
Block a user