Kaynağa Gözat

电脑、人员详情添加编辑

xinyan 7 ay önce
ebeveyn
işleme
ed56956679

+ 87 - 32
src/views/computer-information/components/ComputerDetail.vue

@@ -7,15 +7,22 @@
 import { useResponse } from '/@/utils/useResponse';
 import { ComputerCurrentColumns, ComputerPastColumns } from '/@/views/computer-information/useColumns';
 import * as api from '../api';
-import { Picture as IconPicture } from '@element-plus/icons-vue';
+import { Edit, Picture as IconPicture } from '@element-plus/icons-vue';
 import { useTableData } from '/@/utils/useTableData';
 import { usePagination } from '/@/utils/usePagination';
+import EditComputerInfo from '/@/views/computer-information/components/EditComputerInfo.vue';
+import { ref } from 'vue';
 
 const route = useRoute();
 const id = route.query.id;
-const computerNumber = route.query.computerNumber;
+// const computerNumber = route.query.computerNumber;
 const computerOverview: any = ref([]);
 const overviewLoading = ref();
+const isDrawerVisible = ref(false);
+
+const shopOptions = ref([]);
+const userOptions = ref([]);
+
 const currentView = ref('current');
 const { tableOptions, handlePageChange } = usePagination(fetchComputerData);
 
@@ -38,11 +45,11 @@ const gridOptions: any = reactive({
 	columnConfig: {
 		resizable: true,
 	},
-	pagerConfig: {
-		total: tableOptions.value.total,
-		page: tableOptions.value.page,
-		limit: tableOptions.value.limit,
-	},
+	// pagerConfig: {
+	// 	total: tableOptions.value.total,
+	// 	page: tableOptions.value.page,
+	// 	limit: tableOptions.value.limit,
+	// },
 	loading: false,
 	loadingConfig: {
 		icon: 'vxe-icon-indicator roll',
@@ -52,24 +59,37 @@ const gridOptions: any = reactive({
 	data: [],
 });
 
-function pageChange({ pageSize, currentPage }: any) {
-	gridOptions.pagerConfig.limit = pageSize;
-	gridOptions.pagerConfig.page = currentPage;
-	fetchComputerData();
+async function editItem() {
+  isDrawerVisible.value = true; // 显示 Drawer
+}
+
+async function fetchComputerDetailOverview() {
+  const res = await useResponse(id, api.getComputerDetailOverview, overviewLoading);
+  computerOverview.value = res.data;
 }
 
+// const gridEvents = {
+//   pageChange({ currentPage, pageSize }) {
+//     if (gridOptions.pagerConfig) {
+//       gridOptions.pagerConfig.currentPage = currentPage;
+//       gridOptions.pagerConfig.pageSize = pageSize;
+//       fetchComputerData(currentView.value);
+//     }
+//   }
+// };
+
 // 当前信息、历史记录
 async function fetchComputerData(view) { // 默认为当前视图
   const query = {
-    page: gridOptions.pagerConfig.page,
-    limit: gridOptions.pagerConfig.limit,
+    // page: gridOptions.pagerConfig.currentPage,
+    // limit: gridOptions.pagerConfig.pageSize,
   };
 
   switch (view) {
     case 'current':
       gridOptions.columns = ComputerCurrentColumns;
       currentView.value = 'current';
-      query.computerNumber = computerNumber;
+      query.computerNumber = computerOverview.value.computerNumber;
       await useTableData(api.getCurrentTableData, query, gridOptions);
       break;
     case 'history':
@@ -87,9 +107,31 @@ function switchView(view) {
   }
 }
 
-async function fetchComputerDetailOverview() {
-	const res = await useResponse(id, api.getComputerDetailOverview, overviewLoading);
-	computerOverview.value = res.data;
+function handleRefresh() {
+  fetchComputerDetailOverview();
+  fetchComputerData()
+}
+
+async function fetchShopOptions() {
+  try {
+    const resp = await useResponse(null, api.getShopList);
+    shopOptions.value = resp.data.map((item: any) => {
+      return { value: item.id, label: item.platformNumber };
+    });
+  } catch (e) {
+    console.log('error', e);
+  }
+}
+
+async function fetchUserOptions() {
+  try {
+    const resp = await useResponse(null, api.getUserList);
+    userOptions.value = resp.data.map((item: any) => {
+      return { value: item.id, label: item.name };
+    });
+  } catch (e) {
+    console.log('error', e);
+  }
 }
 
 const getImageSrc = () => {
@@ -113,9 +155,11 @@ const headerCellStyle = () => {
 	};
 };
 
-onMounted(() => {
-	fetchComputerData(currentView.value);
-	fetchComputerDetailOverview();
+onMounted(async () => {
+  await fetchComputerDetailOverview(); // 等待获取详情
+  await fetchComputerData(currentView.value); // 获取电脑数据
+  await fetchShopOptions(); // 获取店铺选项
+  await fetchUserOptions(); // 获取用户选项
 });
 </script>
 
@@ -132,6 +176,7 @@ onMounted(() => {
 					</div>
 				</template>
 			</el-image>
+      <el-button :icon="Edit" link type="warning" @click="editItem"></el-button>
 			<el-col :span="18">
 				<div class="info-container text-lg">
 					<div class="info-column">
@@ -155,7 +200,7 @@ onMounted(() => {
 					<div class="info-column">
 						<div class="font-semibold">
 							使用人:
-							<span class="font-medium italic ml-1.5" style="color: #64748b">{{ computerOverview.user }}</span>
+							<span class="font-medium italic ml-1.5" style="color: #64748b">{{ computerOverview.userName }}</span>
 						</div>
 						<div class="font-semibold">
 							电脑类型:
@@ -171,23 +216,33 @@ onMounted(() => {
 		</el-card>
 		<!-- table-card -->
 		<el-card body-style="padding-top: 10px" class="mt-2.5" shadow="hover" style="border: none">
-			<vxe-grid :cell-style="cellStyle" :header-cell-style="headerCellStyle" v-bind="gridOptions">
+			<vxe-grid :cell-style="cellStyle" :header-cell-style="headerCellStyle" v-bind="gridOptions" v-on="gridEvents">
 				<template #toolbar_buttons>
 					<el-button :type="currentView === 'current' ? 'primary' : 'default'" @click="switchView('current')"> 当前信息 </el-button>
 					<el-button :type="currentView === 'history' ? 'primary' : 'default'" @click="switchView('history')"> 历史记录 </el-button>
 				</template>
-				<template #pager>
-					<vxe-pager
-						v-model:currentPage="gridOptions.pagerConfig.page"
-						v-model:pageSize="gridOptions.pagerConfig.limit"
-						:total="gridOptions.pagerConfig.total"
-						size="small"
-						@page-change="handlePageChange"
-					>
-					</vxe-pager>
-				</template>
+				<!--<template #pager>-->
+				<!--	<vxe-pager-->
+				<!--		v-model:currentPage="tableOptions.page"-->
+				<!--		v-model:pageSize="tableOptions.limit"-->
+				<!--		:total="tableOptions.total"-->
+				<!--		size="small"-->
+				<!--		@page-change="handlePageChange"-->
+				<!--	>-->
+				<!--	</vxe-pager>-->
+				<!--</template>-->
 			</vxe-grid>
 		</el-card>
+    <!-- 编辑 Drawer -->
+    <EditComputerInfo
+    	v-if="isDrawerVisible"
+    	v-model="isDrawerVisible"
+    	:computerOverview
+    	:computerNumber="computerOverview.computerNumber"
+    	:shopOptions="shopOptions"
+    	:userOptions="userOptions"
+    	@refresh="handleRefresh"
+    />
 	</div>
 </template>
 

+ 7 - 7
src/views/computer-information/components/EditComputerInfo.vue

@@ -12,8 +12,8 @@ import * as api from '../api';
 import { EditPen, Picture as IconPicture, Plus, Search } from '@element-plus/icons-vue';
 
 const visible = defineModel({ default: false });
-const { computerInfo, computerNumber , userOptions, shopOptions } = defineProps<{
-  computerInfo: any;
+const { computerOverview, computerNumber , userOptions, shopOptions } = defineProps<{
+  computerOverview: any;
   computerNumber: any;
   userOptions: any;
   shopOptions: any;
@@ -88,7 +88,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
         });
       }
       try {
-        const resp = await useResponse({ id: computerInfo.id, partial: 1, dataToUpload, }, api.updateComputerDetail);
+        const resp = await useResponse({ id: computerOverview.id, partial: 1, dataToUpload, }, api.updateComputerDetail);
         // 检查上传结果并提示用户
         if (resp.code === 2000) {
           ElMessage.success('修改成功');
@@ -112,14 +112,14 @@ const resetForm = (formEl: FormInstance | undefined) => {
 
 function replaceCol() {
   const result = Object.keys(formData).reduce((acc, key) => {
-    if (key in computerInfo) {
-      if (key === 'images' && Array.isArray(computerInfo[key])) {
-        acc[key] = computerInfo[key].map((img: { image: string }) => ({
+    if (key in computerOverview) {
+      if (key === 'images' && Array.isArray(computerOverview[key])) {
+        acc[key] = computerOverview[key].map((img: { image: string }) => ({
           name: '已上传图片',
           url: img.image_url,
         }));
       } else {
-        acc[key] = computerInfo[key];
+        acc[key] = computerOverview[key];
       }
     }
     return acc;

+ 130 - 89
src/views/computer-information/components/InfoCard.vue

@@ -7,7 +7,7 @@
 
 import { ref } from 'vue';
 import { ElCol, ElIcon } from 'element-plus';
-import { EditPen, Picture as IconPicture, Plus, Search } from '@element-plus/icons-vue';
+import { Picture as IconPicture, Plus, Search } from '@element-plus/icons-vue';
 import * as api from '/@/views/computer-information/api';
 import { useRouter } from 'vue-router';
 import { usePagination } from '/@/utils/usePagination';
@@ -20,7 +20,7 @@ const router = useRouter();
 const loading = ref();
 
 const showDialog = ref(false);
-const isDrawerVisible = ref(false);
+// const isDrawerVisible = ref(false);
 
 const computerInfo = ref([]);
 const shopOptions = ref([]);
@@ -34,12 +34,12 @@ async function fetchCardData() {
 		page: tableOptions.value.page,
 		limit: tableOptions.value.limit,
 	};
-	await useTableData(api.getCardData, query, tableOptions,loading);
+	await useTableData(api.getCardData, query, tableOptions, loading);
 }
 
 // 打开创建弹窗
 async function addComputer() {
-  showDialog.value = true;
+	showDialog.value = true;
 }
 
 const checkItem = (item) => {
@@ -47,18 +47,18 @@ const checkItem = (item) => {
 		path: '/computer/detail',
 		query: {
 			id: item.id,
-			computerNumber: item.computerNumber,
+			// computerNumber: item.computerNumber,
 		},
 	});
 };
 
-async function editItem(item) {
-	const res = await useResponse(item.id, api.getComputerDetailOverview);
-	computerInfo.value = res.data;
-	if (computerInfo.value) {
-		isDrawerVisible.value = true; // 显示 Drawer
-	}
-}
+// async function editItem(item) {
+// 	const res = await useResponse(item.id, api.getComputerDetailOverview);
+// 	computerInfo.value = res.data;
+// 	if (computerInfo.value) {
+// 		isDrawerVisible.value = true; // 显示 Drawer
+// 	}
+// }
 
 // 处理图片地址
 const getImageUrl = (images) => {
@@ -67,99 +67,114 @@ const getImageUrl = (images) => {
 };
 
 async function fetchShopOptions() {
-  try {
-    const resp = await useResponse(null, api.getShopList);
-    shopOptions.value = resp.data.map((item: any) => {
-      return { value: item.id, label: item.platformNumber };
-    });
-  } catch (e) {
-    console.log('error', e);
-  }
+	try {
+		const resp = await useResponse(null, api.getShopList);
+		shopOptions.value = resp.data.map((item: any) => {
+			return { value: item.id, label: item.platformNumber };
+		});
+	} catch (e) {
+		console.log('error', e);
+	}
 }
 
 async function fetchUserOptions() {
-  try {
-    const resp = await useResponse(null, api.getUserList);
-    userOptions.value = resp.data.map((item: any) => {
-      return { value: item.id, label: item.name };
-    });
-  } catch (e) {
-    console.log('error', e);
-  }
+	try {
+		const resp = await useResponse(null, api.getUserList);
+		userOptions.value = resp.data.map((item: any) => {
+			return { value: item.id, label: item.name };
+		});
+	} catch (e) {
+		console.log('error', e);
+	}
 }
 
 onMounted(() => {
 	fetchCardData();
-  fetchShopOptions();
-  fetchUserOptions();
+	fetchShopOptions();
+	fetchUserOptions();
 });
 </script>
 
 <template>
-  <!-- 标题区域 -->
-  <el-card class="mb-5"  style="border: none;">
-    <div class="flex justify-between items-baseline">
-      <div>
-        <span class="font-bold text-xl">电脑信息概览</span>
-        <el-divider class=" text-3xl" direction="vertical"/>
-      </div>
-      <span>
-           <el-button :icon="Plus" text bg type="primary" @click="addComputer">添 加</el-button>
-        </span>
-    </div>
-  </el-card>
+	<!-- 标题区域 -->
+	<el-card class="mb-5" style="border: none">
+		<div class="flex justify-between items-baseline">
+			<div>
+				<span class="font-bold text-xl">电脑信息概览</span>
+				<el-divider class="text-3xl" direction="vertical" />
+			</div>
+			<span>
+				<el-button :icon="Plus" bg text type="primary" @click="addComputer">添 加</el-button>
+			</span>
+		</div>
+	</el-card>
 	<!-- 卡片展示区域 -->
-  <el-card class="mb-5" style="border: none;min-height: 83vh;">
-    <el-card class="card-container" v-loading="loading" shadow="never" style="border: none;">
-        <el-row :gutter="20">
-          <el-col v-for="(item, index) in tableOptions.data" :key="index" :lg="6" :md="8" :sm="8" :xl="4" :xs="12" class="my-2.5">
-            <el-card class="item-card" shadow="hover">
-              <el-image :src="getImageUrl(item.images)" alt="电脑图片" class="card-image">
-                <template #error>
-                  <el-icon class="card-image" style="font-size: 4rem">
-                    <icon-picture />
-                  </el-icon>
-                </template>
-              </el-image>
-              <div class="card-content">
-                <div>
-                  <span style="color: #808d97; font-weight: 500">电脑编号: </span>
-                  <span style="font-weight: 500">{{ item.computerNumber }}</span>
-                </div>
-                <div>
-                  <span style="color: #808d97; font-weight: 500">所属店铺: </span>
-                  <span style="font-weight: 500">{{ item.shopName }}</span>
-                </div>
-              </div>
-              <div class="card-footer">
-                <el-button :icon="Search" bg circle text type="primary" @click="checkItem(item)" />
-                <el-button :icon="EditPen" bg circle text type="warning" @click="editItem(item)" />
-              </div>
-            </el-card>
-          </el-col>
-        </el-row>
-    </el-card>
-    <div class="pagination-container" style="position: absolute; right: 40px; bottom: 50px">
-      <el-pagination
-          v-model:current-page="tableOptions.page"
-          v-model:page-size="tableOptions.limit"
-          :page-sizes="[6, 12, 24, 36, 48, 60]"
-          :total="tableOptions.total"
-          background
-          layout="sizes, prev, pager, next, total"
-          @change="handlePageChange"
-      />
-    </div>
-  </el-card>
-  <!-- 新增 Dialog -->
-  <CreateComputer v-model="showDialog" :shopOptions :userOptions @refresh="fetchCardData"></CreateComputer>
-  <!-- 编辑 Drawer -->
-  <EditComputerInfo v-if="isDrawerVisible" @refresh="fetchCardData" v-model="isDrawerVisible" :shopOptions="shopOptions" :userOptions="userOptions" :computerInfo :computerNumber="computerInfo.computerNumber" />
+	<el-card class="flex-grow" style="border: none" :body-style="{ padding: '0px' }">
+		<el-card v-loading="loading" class="card-container" shadow="never" style="border: none">
+			<el-row :gutter="20">
+				<el-col v-for="(item, index) in tableOptions.data" :key="index" :lg="4" :md="6" :sm="8" :xl="4" :xs="12" class="my-2.5">
+          <el-card class="item-card" shadow="hover" :body-style="{ padding: '20px 20px 5px 20px' }">
+						<div class="image-wrapper">
+							<el-image :src="getImageUrl(item.images)" alt="电脑图片" class="card-image">
+								<template #error>
+									<el-icon class="card-image" style="font-size: 4rem">
+										<icon-picture />
+									</el-icon>
+								</template>
+							</el-image>
+						</div>
+						<hr style="box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2)" />
+						<div class="card-content">
+							<div class="text-wrapper">
+								<span style="color: #808d97; font-weight: 500">电脑编号: </span>
+								<span style="font-weight: 500">{{ item.computerNumber }}</span>
+							</div>
+							<div class="text-wrapper">
+								<span style="color: #808d97; font-weight: 500">所属店铺: </span>
+								<span style="font-weight: 500">{{ item.shopName }}</span>
+							</div>
+						</div>
+						<template #footer>
+							<div style="text-align: center; padding: 0 10px">
+								<!--<el-button :icon="Search" bg circle text type="primary" @click="checkItem(item)" />-->
+								<!--<el-button :icon="EditPen" bg circle text type="warning" @click="editItem(item)" />-->
+								<el-button :icon="Search" plain round style="width: 100%" type="primary" @click="checkItem(item)"> 查看详情 </el-button>
+							</div>
+						</template>
+					</el-card>
+				</el-col>
+			</el-row>
+		</el-card>
+		<div class="pagination-container" style="position: absolute; right: 40px; bottom: 50px">
+			<el-pagination
+				v-model:current-page="tableOptions.page"
+				v-model:page-size="tableOptions.limit"
+				:page-sizes="[6, 12, 24, 36, 48, 60]"
+				:total="tableOptions.total"
+				background
+				layout="sizes, prev, pager, next, total"
+				@change="handlePageChange"
+			/>
+		</div>
+	</el-card>
+	<!-- 新增 Dialog -->
+	<CreateComputer v-model="showDialog" :shopOptions :userOptions @refresh="fetchCardData"></CreateComputer>
+	<!-- 编辑 Drawer -->
+	<!--<EditComputerInfo-->
+	<!--	v-if="isDrawerVisible"-->
+	<!--	v-model="isDrawerVisible"-->
+	<!--	:computerInfo-->
+	<!--	:computerNumber="computerInfo.computerNumber"-->
+	<!--	:shopOptions="shopOptions"-->
+	<!--	:userOptions="userOptions"-->
+	<!--	@refresh="fetchCardData"-->
+	<!--/>-->
 </template>
 
 <style lang="scss" scoped>
 .card-container {
 	margin-bottom: 30px;
+  padding: 0;
 }
 
 .item-card {
@@ -172,11 +187,31 @@ onMounted(() => {
 	width: 100%;
 	height: 150px;
 	object-fit: cover;
+	padding-bottom: 10px;
 }
 
 .card-content {
-	padding: 10px;
+	padding-top: 10px;
 	font-size: 14px;
+	max-height: 60px; /* 根据需要设置最大高度 */
+	overflow: hidden; /* 隐藏超出部分 */
+	text-overflow: ellipsis; /* 省略号效果 */
+	display: -webkit-box; /* 适用于多行文本处理 */
+	-webkit-box-orient: vertical; /* 垂直排列 */
+}
+
+.text-wrapper {
+	white-space: nowrap; /* 不换行 */
+	overflow: hidden; /* 隐藏超出部分 */
+	text-overflow: ellipsis; /* 省略号效果 */
+}
+
+.image-wrapper {
+	width: 150px; /* 设置固定宽度 */
+	height: 150px; /* 设置固定高度 */
+	padding-bottom: 10px;
+	margin: 0 auto; /* 横向居中 */
+	overflow: hidden; /* 隐藏溢出部分 */
 }
 
 .card-footer {
@@ -190,4 +225,10 @@ onMounted(() => {
 	justify-content: flex-end;
 	// margin-bottom: 20px;
 }
+
+:deep(.el-card__footer) {
+	border-top: none;
+	padding: 0 0 10px 0;
+}
+
 </style>

+ 10 - 8
src/views/computer-information/useColumns.tsx

@@ -1,19 +1,21 @@
 export const ComputerCurrentColumns = [
-  { field: 'platformNumber', title: '平台编号'},
+  { field: 'platformNumber', title: '电脑编号'},
   { field: 'platform', title: '平台'},
   { field: 'platformName', title: '平台名称'},
-  { field: 'country', title: '区域'},
-  { field: 'userName', title: '使用人'},
+  { field: 'brandName', title: '品牌'},
+  { field: 'operatorName', title: '运营'},
   { field: 'company', title: '所属公司'},
+  { field: 'ipaddress', title: 'IP地址'},
+  { field: 'line', title: '线路'},
+  { field: 'country', title: '区域'},
 ];
 
 export const ComputerPastColumns =[
   { field: 'create_datetime', title: '时间'},
+  { field: 'computerNumber', title: '电脑编号'},
   { field: 'station', title: '工位号'},
-  { field: 'computerNumber', title: '平台编号'},
-  { field: 'platform', title: '平台'},
-  { field: 'platformName', title: '平台名称'},
-  { field: 'company', title: '区域'},
-  { field: 'userName', title: '使用人'},
   { field: 'ipaddress', title: 'IP地址'},
+  { field: 'approveNum', title: '审批单号'},
+  { field: 'people', title: '使用人'},
+  { field: 'shopName', title: '历史店铺名'},
 ]

+ 99 - 97
src/views/employee-information/components/CreateEmployee.vue

@@ -9,136 +9,138 @@ import { useResponse } from '/@/utils/useResponse';
 import * as api from '../api';
 
 const showDialog = defineModel({ default: false });
-const emit = defineEmits([ 'refresh' ]);
+const emit = defineEmits(['refresh']);
+
+const createLoading = ref(false);
 
 // 图片处理
 const upload = ref<UploadInstance>();
+
 // 表单数据
 interface RuleForm {
-  name: string;
-  department: string;
-  phone: string;
-  email: string;
-  user: string;
-  macaddress: string;
-  ipaddress: string;
-  images: UploadFile[];
+	name: string;
+	department: string;
+	phone: string;
+	email: string;
+	user: string;
+	macaddress: string;
+	ipaddress: string;
+	images: UploadFile[];
 }
+
 const ruleFormRef = ref<FormInstance>();
 const formData = reactive<RuleForm>({
-  name: '',
-  department: '',
-  phone: '',
-  email: '',
-  images: [],
+	name: '',
+	department: '',
+	phone: '',
+	email: '',
+	images: [],
 });
 
 const rules = reactive<FormRules<RuleForm>>({
-  name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
-  department: [{ required: true, message: '请输入部门', trigger: 'blur' }],
-  phone: [{ required: true, message: '请输入电话号码', trigger: 'blur' },
-    { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }],
-  email: [{ required: true, message: '请输入邮箱', trigger: 'blur' },
-  { type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }],
+	name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+	department: [{ required: true, message: '请输入部门', trigger: 'blur' }],
+	phone: [
+		{ required: true, message: '请输入电话号码', trigger: 'blur' },
+		{ pattern: /^[0-9]{11}$/, message: '请输入正确的手机号码', trigger: 'blur' },
+	],
+	email: [
+		{ required: true, message: '请输入邮箱', trigger: 'blur' },
+		{ type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' },
+	],
 });
 
-
 // 超过图片限制时触发的回调
 const handleExceed: UploadProps['onExceed'] = (files) => {
-  upload.value!.clearFiles();
-  const file = files[0] as UploadRawFile;
-  file.uid = genFileId();
-  upload.value!.handleStart(file);
+	upload.value!.clearFiles();
+	const file = files[0] as UploadRawFile;
+	file.uid = genFileId();
+	upload.value!.handleStart(file);
 };
 
 const submitForm = async (formEl: FormInstance | undefined) => {
-  if (!formEl) return
-  await formEl.validate((valid, fields) => {
-    if (valid) {
-      handleSave();
-      showDialog.value = false;
-      emit('refresh');
-    } else {
-      ElMessage.error('添加失败');
-    }
-  })
-}
+	if (!formEl) return;
+	await formEl.validate((valid, fields) => {
+		if (valid) {
+			handleSave();
+			showDialog.value = false;
+			emit('refresh');
+			ElMessage.success('添加成功');
+		} else {
+			ElMessage.error('添加失败,请检查表单');
+		}
+	});
+};
+
 // 保存操作
 async function handleSave() {
-  const bodyData = new FormData();
-  const fieldsToAppend = ['name', 'department', 'phone', 'email'];
-  fieldsToAppend.forEach((field) => {
-    bodyData.append(field, formData[field as keyof RuleForm]);
-  });
+	const bodyData = new FormData();
+	const fieldsToAppend = ['name', 'department', 'phone', 'email'];
+	fieldsToAppend.forEach((field) => {
+		bodyData.append(field, formData[field as keyof RuleForm]);
+	});
 
-  if (formData.images.length > 0 && formData.images[0].raw) {
-    bodyData.append('images', formData.images[0].raw); // 使用 'images' 作为字段名,将 File 对象添加到 FormData 中
-  }
-  await useResponse(bodyData, api.createEmployee);
-  if (resp.code === 2000) {
-    ElMessage.success('添加成功');
-  }
+	if (formData.images.length > 0 && formData.images[0].raw) {
+		bodyData.append('images', formData.images[0].raw); // 使用 'images' 作为字段名,将 File 对象添加到 FormData 中
+	}
+	await useResponse(bodyData, api.createEmployee);
+	// if (resp.code === 2000) {
+	//   ElMessage.success('添加成功');
+	// }
 }
 
 // 取消操作
 const handleCancel = () => {
-  showDialog.value = false;
+	showDialog.value = false;
 };
 
-onMounted(() => {
-})
+onMounted(() => {});
 </script>
 
 <template>
-  <el-dialog v-model="showDialog" :close-on-click-modal="false" title="新增电脑信息" width="35%">
-    <el-form
-        ref="ruleFormRef"
-        :model="formData"
-        :rules="rules"
-        class="employee-info-form"
-        label-width="auto"
-        status-icon>
-      <el-form-item label="姓名:" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入姓名" />
-      </el-form-item>
-      <el-form-item label="部门:" prop="department">
-        <el-input v-model="formData.department" placeholder="请输入部门" />
-      </el-form-item>
-      <el-form-item label="电话号码:" prop="phone">
-        <el-input v-model="formData.phone" placeholder="请输入电话号码" />
-      </el-form-item>
-      <el-form-item label="邮箱:" prop="email">
-        <el-input v-model="formData.email" placeholder="请输入邮箱" />
-      </el-form-item>
-      <!-- 人员图片上传 -->
-      <el-form-item :key="images" label="人员图片:">
-        <el-upload
-            ref="upload"
-            v-model:file-list="formData.images"
-            :auto-upload="false"
-            :limit="1"
-            :on-exceed="handleExceed"
-            action="#"
-            list-type="picture-card"
-        >
-          <el-icon>
-            <Plus />
-          </el-icon>
-        </el-upload>
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <div class="dialog-footer">
-        <el-button type="primary" @click="submitForm(ruleFormRef)">保存</el-button>
-        <el-button @click="handleCancel">取消</el-button>
-      </div>
-    </template>
-  </el-dialog>
+	<el-dialog v-model="showDialog" :close-on-click-modal="false" title="新增电脑信息" width="35%">
+		<el-form ref="ruleFormRef" :model="formData" :rules="rules" class="employee-info-form" label-width="auto" status-icon>
+			<el-form-item label="姓名:" prop="name">
+				<el-input v-model="formData.name" placeholder="请输入姓名" />
+			</el-form-item>
+			<el-form-item label="部门:" prop="department">
+				<el-input v-model="formData.department" placeholder="请输入部门" />
+			</el-form-item>
+			<el-form-item label="电话号码:" prop="phone">
+				<el-input v-model="formData.phone" placeholder="请输入电话号码" />
+			</el-form-item>
+			<el-form-item label="邮箱:" prop="email">
+				<el-input v-model="formData.email" placeholder="请输入邮箱" />
+			</el-form-item>
+			<!-- 人员图片上传 -->
+			<el-form-item :key="images" label="人员图片:">
+				<el-upload
+					ref="upload"
+					v-model:file-list="formData.images"
+					:auto-upload="false"
+					:limit="1"
+					:on-exceed="handleExceed"
+					action="#"
+					list-type="picture-card"
+				>
+					<el-icon>
+						<Plus />
+					</el-icon>
+				</el-upload>
+			</el-form-item>
+		</el-form>
+		<template #footer>
+			<div class="dialog-footer">
+				<el-button :loading="createLoading" type="primary" @click="submitForm(ruleFormRef)">保存</el-button>
+				<el-button @click="handleCancel">取消</el-button>
+			</div>
+		</template>
+	</el-dialog>
 </template>
 
 <style scoped>
 .dialog-footer {
-  margin-bottom: 10px;
-  text-align: center;
+	margin-bottom: 10px;
+	text-align: center;
 }
 </style>

+ 11 - 9
src/views/employee-information/components/EditEmployeeInfo.vue

@@ -11,8 +11,8 @@ import { useResponse } from '/@/utils/useResponse';
 import * as api from '../api';
 
 const visible = defineModel({ default: false });
-const { employeeInfo, name } = defineProps<{
-	employeeInfo: any;
+const { employeeOverview, name } = defineProps<{
+	employeeOverview: any;
 	name: any;
 }>();
 
@@ -45,8 +45,10 @@ const formData = reactive<RuleForm>({
 const rules = reactive<FormRules<RuleForm>>({
 	name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
 	department: [{ required: true, message: '请输入部门', trigger: 'blur' }],
-	phone: [{ required: true, message: '请输入电话号码', trigger: 'blur' }],
-	email: [{ required: true, message: '请输入所属商铺', trigger: 'blur' }],
+  phone: [{ required: true, message: '请输入电话号码', trigger: 'blur' },
+    { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }],
+  email: [{ required: true, message: '请输入邮箱', trigger: 'blur' },
+    { type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }],
 });
 
 onBeforeMount(() => {
@@ -82,7 +84,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
 				});
 			}
 			try {
-				const resp = await useResponse({ id: employeeInfo.id, partial: 1, dataToUpload, }, api.updateEmployeeDetail);
+				const resp = await useResponse({ id: employeeOverview.id, partial: 1, dataToUpload, }, api.updateEmployeeDetail);
 				// 检查上传结果并提示用户
 				if (resp.code === 2000) {
 					ElMessage.success('修改成功');
@@ -106,15 +108,15 @@ const resetForm = (formEl: FormInstance | undefined) => {
 
 function replaceCol() {
 	const result = Object.keys(formData).reduce((acc, key) => {
-		if (key in employeeInfo) {
+		if (key in employeeOverview) {
 			// 如果字段是 images,则转换图片格式
-			if (key === 'images' && Array.isArray(employeeInfo[key])) {
-				acc[key] = employeeInfo[key].map((img: { image: string }) => ({
+			if (key === 'images' && Array.isArray(employeeOverview[key])) {
+				acc[key] = employeeOverview[key].map((img: { image: string }) => ({
 					name: '已上传图片',
 					url: img.image_url,
 				}));
 			} else {
-				acc[key] = employeeInfo[key];
+				acc[key] = employeeOverview[key];
 			}
 		}
 		return acc;

+ 18 - 2
src/views/employee-information/components/EmployeeDetail.vue

@@ -7,14 +7,18 @@
 import { useResponse } from '/@/utils/useResponse';
 import { EmployeeShopColumns, EmployeeComputerColumns } from '/@/views/employee-information/useColumns';
 import * as api from '../api';
-import { Picture as IconPicture } from '@element-plus/icons-vue';
+import { Edit, Picture as IconPicture } from '@element-plus/icons-vue';
 import { useTableData } from '/@/utils/useTableData';
 import { usePagination } from '/@/utils/usePagination';
+import EditEmployeeInfo from '/@/views/employee-information/components/EditEmployeeInfo.vue';
+import { ref } from 'vue';
 
 const route = useRoute();
 const id = route.query.id;
 const employeeOverview: any = ref([]);
 const overviewLoading = ref();
+const isDrawerVisible = ref(false);
+
 const currentView = ref('shop');
 const { tableOptions, handlePageChange } = usePagination(fetchEmployeeData);
 
@@ -86,6 +90,10 @@ function switchView(view) {
   }
 }
 
+async function editItem() {
+  isDrawerVisible.value = true; // 显示 Drawer
+}
+
 async function fetchEmployeeDetailOverview() {
   const res = await useResponse(id, api.getEmployeeDetailOverview, overviewLoading);
   employeeOverview.value = res.data;
@@ -112,9 +120,14 @@ const headerCellStyle = () => {
   };
 };
 
-onMounted(() => {
+function handleRefresh() {
+  fetchEmployeeDetailOverview();
   fetchEmployeeData(currentView.value);
+}
+
+onMounted(() => {
   fetchEmployeeDetailOverview();
+  fetchEmployeeData(currentView.value);
 });
 </script>
 
@@ -131,6 +144,7 @@ onMounted(() => {
           </div>
         </template>
       </el-image>
+      <el-button :icon="Edit" link type="warning" @click="editItem"></el-button>
       <el-col :span="18">
         <div class="info-container text-lg">
           <div class="info-column">
@@ -173,6 +187,8 @@ onMounted(() => {
         <!--</template>-->
       </vxe-grid>
     </el-card>
+    <!-- 编辑 Drawer -->
+    <EditEmployeeInfo v-if="isDrawerVisible" v-model="isDrawerVisible" :employeeOverview :name="employeeOverview.name" @refresh="handleRefresh" />
   </div>
 </template>
 

+ 71 - 51
src/views/employee-information/components/InfoCard.vue

@@ -8,7 +8,7 @@ import { useRouter } from 'vue-router';
 import { ref } from 'vue';
 import { usePagination } from '/@/utils/usePagination';
 import { useTableData } from '/@/utils/useTableData';
-import { Delete, EditPen, Picture as IconPicture, Plus, Search } from '@element-plus/icons-vue';
+import { EditPen, Picture as IconPicture, Plus, Search } from '@element-plus/icons-vue';
 import * as api from '/@/views/employee-information/api';
 import { useResponse } from '/@/utils/useResponse';
 import EditEmployeeInfo from '/@/views/employee-information/components/EditEmployeeInfo.vue';
@@ -19,7 +19,7 @@ const router = useRouter();
 const loading = ref();
 // 创建弹窗
 const showDialog = ref(false);
-const isDrawerVisible = ref(false);
+// const isDrawerVisible = ref(false);
 
 const employeeInfo = ref([]);
 const { tableOptions, handlePageChange } = usePagination(fetchCardData);
@@ -30,7 +30,7 @@ async function fetchCardData() {
 		page: tableOptions.value.page,
 		limit: tableOptions.value.limit,
 	};
-	await useTableData(api.getCardData, query, tableOptions);
+	await useTableData(api.getCardData, query, tableOptions,loading);
 }
 
 async function addEmployee() {
@@ -46,13 +46,13 @@ const checkItem = (item) => {
 	});
 };
 
-async function editItem(item) {
-	const res = await useResponse(item.id, api.getEmployeeDetailOverview);
-	employeeInfo.value = res.data;
-	if (employeeInfo.value) {
-		isDrawerVisible.value = true; // 显示 Drawer
-	}
-}
+// async function editItem(item) {
+// 	const res = await useResponse(item.id, api.getEmployeeDetailOverview);
+// 	employeeInfo.value = res.data;
+// 	if (employeeInfo.value) {
+// 		isDrawerVisible.value = true; // 显示 Drawer
+// 	}
+// }
 
 const getImageUrl = (images) => {
 	// 如果有图片,返回第一个图片的 image_url,否则返回占位图
@@ -78,18 +78,21 @@ onMounted(() => {
 		</div>
 	</el-card>
 	<!-- 卡片展示区域 -->
-	<el-card class="mb-5" style="border: none; min-height: 83vh">
+  <el-card class="flex-grow" style="border: none" :body-style="{ padding: '0px' }">
 		<el-card v-loading="loading" class="card-container" shadow="never" style="border: none">
 			<el-row :gutter="20">
 				<el-col v-for="(item, index) in tableOptions.data" :key="index" :lg="6" :md="8" :sm="8" :xl="4" :xs="12" class="my-2.5">
-					<el-card class="item-card" shadow="hover">
-						<el-image :src="getImageUrl(item.images)" alt="电脑图片" class="card-image">
-							<template #error>
-								<el-icon class="card-image" style="font-size: 4rem">
-									<icon-picture />
-								</el-icon>
-							</template>
-						</el-image>
+          <el-card class="item-card" shadow="hover" :body-style="{ padding: '20px 20px 5px 20px' }">
+          <div class="image-wrapper">
+							<el-image :src="getImageUrl(item.images)" alt="电脑图片" class="card-image">
+								<template #error>
+									<el-icon class="card-image" style="font-size: 4rem">
+										<icon-picture />
+									</el-icon>
+								</template>
+							</el-image>
+						</div>
+						<hr style="box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2)" />
 						<div class="card-content">
 							<div>
 								<span style="color: #808d97; font-weight: 500">姓名: </span>
@@ -100,64 +103,81 @@ onMounted(() => {
 								<span style="font-weight: 500">{{ item.department }}</span>
 							</div>
 						</div>
-						<div class="card-footer">
-							<el-button :icon="Search" bg circle text type="primary" @click="checkItem(item)" />
-							<el-button :icon="EditPen" bg circle text type="warning" @click="editItem(item)" />
-							<!--<el-button :icon="Delete" bg circle text type="danger" @click="deleteItem(item)" />-->
-						</div>
+            <template #footer>
+              <div style="text-align: center; padding: 0 10px">
+                <!--<el-button :icon="Search" bg circle text type="primary" @click="checkItem(item)" />-->
+                <!--<el-button :icon="EditPen" bg circle text type="warning" @click="editItem(item)" />-->
+                <el-button :icon="Search" plain round style="width: 100%" type="primary" @click="checkItem(item)"> 查看详情 </el-button>
+              </div>
+            </template>
 					</el-card>
 				</el-col>
 			</el-row>
 		</el-card>
-    <div class="pagination-container" style="position: absolute; right: 40px; bottom: 50px">
-      <el-pagination
-          v-model:current-page="tableOptions.page"
-          v-model:page-size="tableOptions.limit"
-          :page-sizes="[6, 12, 24, 36, 48, 60]"
-          :total="tableOptions.total"
-          background
-          layout="sizes, prev, pager, next, total"
-          @change="handlePageChange"
-      />
-    </div>
+		<div class="pagination-container" style="position: absolute; right: 40px; bottom: 50px">
+			<el-pagination
+				v-model:current-page="tableOptions.page"
+				v-model:page-size="tableOptions.limit"
+				:page-sizes="[6, 12, 24, 36, 48, 60]"
+				:total="tableOptions.total"
+				background
+				layout="sizes, prev, pager, next, total"
+				@change="handlePageChange"
+			/>
+		</div>
 	</el-card>
 	<!-- 新增 Dialog -->
 	<CreateEmployee v-model="showDialog" @refresh="fetchCardData" />
 	<!-- 编辑 Drawer -->
-	<EditEmployeeInfo v-if="isDrawerVisible" @refresh="fetchCardData" v-model="isDrawerVisible" :employeeInfo :name="employeeInfo.name" />
+	<!--<EditEmployeeInfo v-if="isDrawerVisible" v-model="isDrawerVisible" :employeeInfo :name="employeeInfo.name" @refresh="fetchCardData" />-->
 </template>
 
 <style lang="scss" scoped>
 .card-container {
-	margin-bottom: 30px;
+  margin-bottom: 30px;
+  padding:0;
 }
 
 .item-card {
-	border-radius: 10px;
-	overflow: hidden;
-	position: relative;
+  border-radius: 10px;
+  overflow: hidden;
+  position: relative;
 }
 
 .card-image {
-	width: 100%;
-	height: 150px;
-	object-fit: cover;
+  width: 100%;
+  height: 150px;
+  object-fit: cover;
+  padding-bottom: 10px;
 }
 
 .card-content {
-	padding: 10px;
-	font-size: 14px;
+  padding-top: 10px;
+  font-size: 14px;
+}
+
+.image-wrapper {
+  width: 150px; /* 设置固定宽度 */
+  height: 150px; /* 设置固定高度 */
+  padding-bottom: 10px;
+  margin: 0 auto; /* 横向居中 */
+  overflow: hidden; /* 隐藏溢出部分 */
 }
 
 .card-footer {
-	display: flex;
-	justify-content: flex-end;
-	// padding: 10px;
+  display: flex;
+  justify-content: flex-end;
+  // padding: 10px;
 }
 
 .pagination-container {
-	display: flex;
-	justify-content: flex-end;
-	// margin-bottom: 20px;
+  display: flex;
+  justify-content: flex-end;
+  // margin-bottom: 20px;
+}
+
+:deep(.el-card__footer) {
+  border-top: none;
+  padding: 0 0 10px 0;
 }
 </style>