Browse Source

no message

kllay 1 day ago
parent
commit
5ca5488eb4

+ 39 - 1
src/utils/service.ts

@@ -204,7 +204,7 @@ export const requestForMock = createRequestFunction(serviceForMock);
  * @param method
  * @param filename
  */
-export const downloadFile = function ({ url, params, method, filename = '文件导出' }: any) {
+export const downloadFile = function ({ url,params, method, filename = '文件导出' }: any) {
 	// return request({ url: url, method: method, params: params })
 	// 	.then((res: any) => successMessage(res.msg));
 	request({
@@ -240,3 +240,41 @@ export const downloadFile = function ({ url, params, method, filename = '文件
 		}
 	})
 }
+
+
+export const downloadFilePost = function ({ url,data, method, filename = '文件导出' }: any) {
+	// return request({ url: url, method: method, params: params })
+	// 	.then((res: any) => successMessage(res.msg));
+	request({
+		url: url,
+		method: method,
+		data: data,
+		responseType: 'blob'
+		// headers: {Accept: 'application/vnd.openxmlformats-officedocument'}
+	}).then((res: any) => {
+		// console.log(res.headers['content-type']); // 根据content-type不同来判断是否异步下载
+		// if (res.headers && res.headers['Content-type'] === 'application/json') return successMessage('导入任务已创建,请前往‘下载中心’等待下载');
+		if (res.headers['content-type'] === 'application/json') return successMessage('导入任务已创建,请前往‘下载中心’等待下载');
+		// const xlsxName = window.decodeURI(res.headers['Content-Disposition'].split('=')[1])
+		let xlsxName='';
+		const disposition = res.headers['content-disposition'];
+		if (disposition && disposition.includes('filename=')) {
+			const match = disposition.match(/filename="?([^"]+)"?/);
+			if (match && match[1]) {
+				xlsxName = decodeURIComponent(match[1]);
+			}
+		}
+		const fileName = xlsxName || `${filename}.xlsx`
+		if (res) {
+			const blob = new Blob([res.data], { type: 'charset=utf-8' })
+			const elink = document.createElement('a')
+			elink.download = fileName
+			elink.style.display = 'none'
+			elink.href = URL.createObjectURL(blob)
+			document.body.appendChild(elink)
+			elink.click()
+			URL.revokeObjectURL(elink.href) // 释放URL 对象0
+			document.body.removeChild(elink)
+		}
+	})
+}

+ 71 - 2
src/views/system/allusers/index.vue

@@ -8,22 +8,91 @@
 
 		</fs-crud>
 
+		<el-dialog v-model="importDialogVisible" title="批量导入设备" width="30%">
+		<el-upload
+			ref="uploadRef"
+			:auto-upload="false"
+			:file-list="fileList"
+			:limit="1"
+			:on-change="handleFileChange"
+			:before-upload="() => false"
+			accept=".xls,.xlsx"
+		>
+			<el-button type="primary">选择文件</el-button>
+		</el-upload>
+		<template #footer>
+			<el-button @click="importDialogVisible = false">取消</el-button>
+			<el-button type="primary" @click="submitImport">确认导入</el-button>
+		</template>
+		</el-dialog>
+
 	</fs-page>
 </template>
 
 <script lang="ts" setup name="allusers">
 import { useFs } from '@fast-crud/fast-crud';
-import { onMounted } from 'vue';
+import { onMounted,ref } from 'vue';
 import { GetPermission } from './api';
 import { createCrudOptions } from './crud';
 import { handleColumnPermission } from '/@/utils/columnPermission';
 import { downloadFile } from '/@/utils/service';
+import { request } from '/@/utils/service';
+import Cookies from 'js-cookie';
+import { ElMessage } from 'element-plus';
+
+const importDialogVisible = ref(false); 
+const fileList = ref<File[]>([]);
+
 const { crudBinding, crudRef, crudExpose, crudOptions, resetCrudOptions } = useFs({ createCrudOptions });
 
 const handleBatchImport = () => {
-
+	importDialogVisible.value = true;
 }
 
+
+const handleFileChange = (file: any) => {
+	fileList.value = [file.raw];
+};
+
+const submitImport = async () => {
+  if (fileList.value.length === 0) {
+    ElMessage.warning('请先选择文件');
+    return;
+  }
+
+  const rawFile = fileList.value[0]; 
+  if (!rawFile) {
+    ElMessage.error('文件无效,请重新选择');
+    return;
+  }
+
+
+  const formData = new FormData();
+  formData.append('file', rawFile);
+  const token = Cookies.get('token'); 
+  try {
+	await request({
+		url: '/api/system/app_user/batch_import/',
+		method: 'post',
+		data: formData,
+		headers: {
+			'Content-Type': 'multipart/form-data',
+			"Authorization": token ? `JWT ${token}` : ''
+		}
+	}).then((res: any) => {
+		console.log("导入resssss:::",res)
+		ElMessage.success('导入成功');
+		importDialogVisible.value = false;
+		fileList.value = [];
+		crudExpose.doRefresh(); 
+	})
+  } catch (error) {
+    ElMessage.error('导入失败,请检查文件格式或内容');
+    console.error(error);
+  }
+};
+
+
 const handleDownloadTemplate = () => {
 	downloadFile({
 		url: '/api/system/app_user/download_template/',

+ 16 - 1
src/views/system/device/crud.tsx

@@ -1,4 +1,4 @@
-import { AddReq, compute,useCrud , CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, uiContext, UserPageQuery, } from '@fast-crud/fast-crud';
+import { AddReq, compute,useCrud ,useExpose, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, uiContext, UserPageQuery, } from '@fast-crud/fast-crud';
 import dayjs from 'dayjs';
 import * as api from './api';
 import { uploadFile } from './api';
@@ -14,6 +14,7 @@ import { ElTable, ElTableColumn, ElLoading } from 'element-plus';
 
 
 
+
 const BorrowRecords = defineComponent({
 	props: { form: Object },
 	setup(props) {
@@ -100,7 +101,17 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 		return await api.AddObj(form);
 	};
 
+	const selectedIds = ref([]);
+
+	const onSelectionChange = (changed) => {
+		console.log("selection", changed);
+		selectedIds.value = changed.map((item) => item.id);
+	};
+
+	crudExpose.selectedIds = selectedIds;
+
 	return {
+		// selectedIds,
 		crudOptions: {
 			request: {
 				pageRequest,
@@ -108,6 +119,10 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
 				editRequest,
 				delRequest,
 			},
+			table: {
+				rowKey: "id", 
+				onSelectionChange
+			},
 			toolbar:{
 				show:true,
 			},

+ 87 - 4
src/views/system/device/index.vue

@@ -13,10 +13,28 @@
 			</el-tooltip> 
 			</template>-->
 		</fs-crud>
+		<el-dialog v-model="importDialogVisible" title="批量导入设备" width="30%">
+		<el-upload
+			ref="uploadRef"
+			:auto-upload="false"
+			:file-list="fileList"
+			:limit="1"
+			:on-change="handleFileChange"
+			:before-upload="() => false"
+			accept=".xls,.xlsx"
+		>
+			<el-button type="primary">选择文件</el-button>
+		</el-upload>
+		<template #footer>
+			<el-button @click="importDialogVisible = false">取消</el-button>
+			<el-button type="primary" @click="submitImport">确认导入</el-button>
+		</template>
+		</el-dialog>
+
 	</fs-page>
 </template>
 <script lang="ts" setup name="device">
-import { onMounted } from 'vue';
+import { onMounted ,ref} from 'vue';
 import { useFs} from '@fast-crud/fast-crud';
 import { createCrudOptions } from './crud';
 import * as api from './api';
@@ -25,14 +43,79 @@ import * as api from './api';
 import { ElMessage } from 'element-plus';
 import axios from 'axios'
 import Cookies from 'js-cookie';
-import { downloadFile } from '/@/utils/service';
+import { downloadFile,downloadFilePost } from '/@/utils/service';
+import { request } from '/@/utils/service';
 
 const { crudBinding, crudRef, crudExpose, crudOptions, resetCrudOptions } = useFs({ createCrudOptions });
 
+
+const importDialogVisible = ref(false); 
+const fileList = ref<File[]>([]);
+
+
+
 const handleBatchImport = () => {
+  importDialogVisible.value = true;
+};
 
-}
-const handleExports = () => {
+const handleFileChange = (file: any) => {
+  	fileList.value = [file.raw];
+};
+
+const submitImport = async () => {
+  if (fileList.value.length === 0) {
+    ElMessage.warning('请先选择文件');
+    return;
+  }
+
+  const rawFile = fileList.value[0]; 
+  if (!rawFile) {
+    ElMessage.error('文件无效,请重新选择');
+    return;
+  }
+
+
+  const formData = new FormData();
+  formData.append('file', rawFile);
+  const token = Cookies.get('token'); 
+  try {
+	await request({
+		url: '/api/system/device/batch_import/',
+		method: 'post',
+		data: formData,
+		headers: {
+			'Content-Type': 'multipart/form-data',
+			"Authorization": token ? `JWT ${token}` : ''
+		}
+	}).then((res: any) => {
+		console.log("导入resssss:::",res)
+		ElMessage.success('导入成功');
+		importDialogVisible.value = false;
+		fileList.value = [];
+		crudExpose.doRefresh(); 
+	})
+  } catch (error) {
+    ElMessage.error('导入失败,请检查文件格式或内容');
+    console.error(error);
+  }
+};
+
+
+const handleExports = async () => {
+	const selectedRows = (crudExpose as any).selectedIds?.value || [];	
+	console.log("selectedRows::",selectedRows)
+	if (selectedRows.length === 0) {
+		ElMessage.warning('请先选择要导出的设备')
+		return
+	}
+	downloadFilePost({
+	url: '/api/system/device/export_selected/',
+	method: 'post',
+	data: {
+		device_ids: selectedRows
+	},
+	filename: '设备导出'
+	})
 
 }