Browse Source

修改对账单导出格式,以及排产单页面类型显示bug

klzhangweiya 1 year ago
parent
commit
eaf0662b0c

+ 5 - 7
app/wx-app/shims-uni.d.ts

@@ -1,10 +1,8 @@
-/// <reference types='@dcloudio/types' />
-import 'vue'
+import '@vue/runtime-core'
 
 declare module '@vue/runtime-core' {
-  type Hooks = App.AppInstance & Page.PageInstance;
-
-  interface ComponentCustomOptions extends Hooks {
-
-  }
+	interface ComponentCustomProperties {
+		__VLS_elementAsFunction: any
+		__VLS_intrinsicElements: any
+	}
 }

+ 1 - 1
app/wx-app/src/pages/login/index.vue

@@ -83,11 +83,11 @@ const handleLogin = async () => {
 			password: form.value.password,
 			grant_type: 'password',
 		})
-
 		userStore.setToken(res.access_token)
 		uni.showToast({ title: '登录成功' })
 		uni.switchTab({ url: '/pages/home/index' })
 	} catch (error) {
+		console.error('登录失败', error)
 		uni.showToast({ title: '登录失败', icon: 'none' })
 	}
 }

+ 172 - 152
app/wx-app/src/pages/profile/index.vue

@@ -1,242 +1,262 @@
 <template>
 	<view class="container">
-		<!-- 用户信息区域 -->
-		<view class="user-info">
-			<button class="avatar-button" open-type="chooseAvatar" @chooseavatar="handleChooseAvatar" @click="handleWxLogin">
+		<!-- 顶部用户信息 -->
+		<view class="header">
+			<button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="handleChooseAvatar" @click="handleWxLogin">
 				<image class="avatar" :src="userInfo.avatarUrl || '/static/image/M.png'" mode="aspectFill"></image>
 			</button>
-			<view class="nickname">{{ userInfo.nickName || '未登录' }}</view>
+			<text class="username">{{ userStore.userInfo?.username || '未登录' }}</text>
+		</view>
+
+		<!-- 数据统计 -->
+		<view class="stats">
+			<view class="stat-item">
+				<text class="value">{{ inventoryCount }}</text>
+				<text class="label">当前库存</text>
+			</view>
+			<view class="stat-item">
+				<text class="value">{{ pendingOrders }}</text>
+				<text class="label">待处理订单</text>
+			</view>
 		</view>
 
 		<!-- 功能入口 -->
 		<view class="menu-list">
-			<navigator url="/pages/order/index" class="menu-item">
-				<image class="icon" src="/static/icons/order.png"></image>
-				<text>企业订单</text>
-				<image class="arrow" src="/static/icons/arrow-right.png"></image>
-			</navigator>
 			<navigator url="/pages/inventory/index" class="menu-item">
 				<image class="icon" src="/static/icons/inventory.png"></image>
-				<text>库存管理</text>
+				<text class="title">库存管理</text>
+				<view class="badge">{{ inventoryPending }}项需处理</view>
 				<image class="arrow" src="/static/icons/arrow-right.png"></image>
 			</navigator>
-			<navigator url="/pages/settings/index" class="menu-item">
-				<image class="icon" src="/static/icons/settings_light.png"></image>
-				<text>设置</text>
+
+			<navigator url="/pages/order/index" class="menu-item">
+				<image class="icon" src="/static/icons/order.png"></image>
+				<text class="title">企业订单</text>
+				<view class="badge">{{ orderPending }}条新订单</view>
 				<image class="arrow" src="/static/icons/arrow-right.png"></image>
 			</navigator>
 		</view>
+
+		<!-- 退出登录 -->
 		<view class="logout-container">
-			<button class="logout-button" @click="handleLogout">退出登录</button>
+			<button class="logout-btn" @click="handleLogout">退出登录</button>
 		</view>
 	</view>
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted } from 'vue'
+import { ref, computed } from 'vue'
 import { useUserStore } from '@/stores/user'
-import type { WxLoginResponse } from '@/api/types'
-import { wxLogin, saveUserInfo, wxDecrypt } from '@/api'
+import { wxLogin } from '@/api'
+
+interface UserInventory {
+	status: string
+}
+
+interface UserOrder {
+	status: string
+}
 
 const userStore = useUserStore()
 
+// 用户信息
 const userInfo = ref({
-	avatarUrl: '',
-	nickName: '',
+	avatarUrl: userStore.userInfo?.avatarUrl || '',
+})
+
+// 类型安全的计算属性
+const inventoryCount = computed(() => (userStore as any).inventory?.length || 0)
+const pendingOrders = computed(() => {
+	const orders = ((userStore as any).orders as UserOrder[]) || []
+	return orders.filter((o) => o.status === 'pending').length
+})
+const inventoryPending = computed(() => {
+	const inventory = ((userStore as any).inventory as UserInventory[]) || []
+	return inventory.filter((i) => i.status === 'low').length
+})
+const orderPending = computed(() => {
+	const orders = ((userStore as any).orders as UserOrder[]) || []
+	return orders.filter((o) => o.status === 'new').length
 })
 
 // 微信登录
 const handleWxLogin = () => {
-	uni.showLoading({
-		title: '登录中...',
-		mask: true,
-	})
+	uni.showLoading({ title: '登录中...', mask: true })
 
 	uni.login({
 		provider: 'weixin',
-		success: async (loginRes) => {
+		success: async (res) => {
 			try {
-				// 获取code
-				const code = loginRes.code as string
-				// 获取系统登录token
-				const token = userStore.token
-				if (!token) {
-					uni.showToast({
-						title: '请先登录系统',
-						icon: 'none',
-					})
-					uni.reLaunch({
-						url: '/pages/login/index',
-					})
+				const code = res.code
+				if (!userStore.token) {
+					uni.showToast({ title: '请先登录系统', icon: 'none' })
+					uni.reLaunch({ url: '/pages/login/index' })
 					return
 				}
 
-				// 调用后端接口获取openid,传递系统token
 				const result = await wxLogin(code)
-				console.log('result:', result)
-				if (result.openid) {
-					// 已通过handleUserAuth获取用户信息
+				if (result.session_key) {
 					userStore.setSessionKey(result.session_key)
-					//await getUserProfile()
 				}
 			} catch (err) {
 				uni.hideLoading()
-				uni.showToast({
-					title: '登录失败',
-					icon: 'none',
-				})
-				console.error('wxLogin error:', err)
+				uni.showToast({ title: '登录失败', icon: 'none' })
+				console.error('微信登录失败:', err)
 			}
 		},
 		fail: (err: any) => {
 			uni.hideLoading()
-			uni.showToast({
-				title: '微信登录失败',
-				icon: 'none',
-			})
-			console.error('wxLogin fail:', err)
+			uni.showToast({ title: '授权失败', icon: 'none' })
+			console.error('微信登录失败:', err)
 		},
 	})
 }
 
-// 处理选择头像
-const handleChooseAvatar = (e: any) => {
-	const avatarUrl = e.detail.avatarUrl
-	userInfo.value.avatarUrl = avatarUrl
-	userStore.setUserInfo({
-		...userStore.userInfo,
-		avatarUrl: avatarUrl,
-	})
-	uni.showToast({
-		title: '头像更新成功',
-		icon: 'success',
-	})
+// 处理头像选择
+const handleChooseAvatar = async (e: { detail: { avatarUrl: string } }) => {
+	try {
+		const avatarUrl = e.detail.avatarUrl
+		userInfo.value.avatarUrl = avatarUrl
+		userStore.setUserInfo({
+			...userStore.userInfo,
+			avatarUrl,
+		})
+	} catch (err) {
+		console.error('头像更新失败:', err)
+	}
 }
 
 // 退出登录
 const handleLogout = () => {
-	uni.showModal({
-		title: '提示',
-		content: '确定要退出登录吗?',
-		success: (res) => {
-			if (res.confirm) {
-				// 清除token
-				userStore.clearToken()
-				// 跳转到登录页
-				uni.reLaunch({
-					url: '/pages/login/index',
-				})
-			}
-		},
-	})
+	userStore.clearToken()
+	uni.reLaunch({ url: '/pages/login/index' })
 }
-
-// 页面加载时检查授权状态
-onMounted(() => {
-	//checkAuth()
-})
 </script>
 
 <style lang="scss" scoped>
-// 导入全局变量
-@use '~@/styles/variables.scss' as *;
-
-// 页面容器
 .container {
-	padding: 20rpx;
+	padding: 30rpx;
+	background: #f8f8f8;
+	min-height: 100vh;
+}
 
-	// 用户信息区域
-	.user-info {
+.header {
+	background: #fff;
+	border-radius: 24rpx;
+	padding: 40rpx 0;
+	margin-bottom: 30rpx;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+
+	.avatar-wrapper {
+		width: 160rpx;
+		height: 160rpx;
+		border-radius: 50%;
+		border: 4rpx solid #f1f1f1;
+		overflow: hidden;
+
+		.avatar {
+			width: 100%;
+			height: 100%;
+		}
+	}
+
+	.username {
+		font-size: 36rpx;
+		color: #333;
+		font-weight: 500;
+		margin-top: 20rpx;
+	}
+}
+
+.stats {
+	background: #fff;
+	border-radius: 24rpx;
+	padding: 30rpx 0;
+	margin-bottom: 30rpx;
+	display: flex;
+	justify-content: space-around;
+
+	.stat-item {
 		display: flex;
 		flex-direction: column;
 		align-items: center;
-		padding: 40rpx;
-		background: $white;
-		border-radius: 16rpx;
-		margin-bottom: 20rpx;
 
-		.avatar {
-			position: absolute;
-			z-index: 5;
-			width: 120rpx;
-			height: 120rpx;
-			left: 0;
-			border-radius: 50%;
-			cursor: pointer;
-			transition: transform 0.2s ease;
-			&:active {
-				transform: scale(0.95);
-			}
+		.value {
+			font-size: 48rpx;
+			color: #007aff;
+			font-weight: bold;
+			margin-bottom: 10rpx;
 		}
 
-		.avatar-button {
-			position: relative;
-			top: 10%;
-			width: 120rpx;
-			height: 120rpx;
-			border: none;
-			outline: none;
-			background: transparent;
-			cursor: pointer;
-			z-index: 10;
-			border-radius: 50%;
-			overflow: hidden;
-			padding: 0;
-		}
-		.nickname {
-			margin-top: 20rpx;
-			font-size: 36rpx;
-			color: $gray-333;
-			font-weight: 500;
+		.label {
+			font-size: 28rpx;
+			color: #666;
 		}
 	}
 }
 
-// 菜单列表
 .menu-list {
-	background: $white;
-	border-radius: 16rpx;
+	background: #fff;
+	border-radius: 24rpx;
+	padding: 0 30rpx;
 
 	.menu-item {
-		@include flex-center;
-		padding: 30rpx;
-		border-bottom: 1rpx solid $gray-f5;
+		display: flex;
+		align-items: center;
+		padding: 30rpx 0;
+		border-bottom: 1rpx solid #eee;
 
 		&:last-child {
 			border-bottom: none;
 		}
 
 		.icon {
-			width: 40rpx;
-			height: 40rpx;
+			width: 48rpx;
+			height: 48rpx;
+			margin-right: 20rpx;
+		}
+
+		.title {
+			flex: 1;
+			font-size: 32rpx;
+			color: #333;
+		}
+
+		.badge {
+			background: #ff5a5f;
+			color: #fff;
+			font-size: 24rpx;
+			padding: 6rpx 16rpx;
+			border-radius: 24rpx;
 			margin-right: 20rpx;
 		}
 
 		.arrow {
-			width: 24rpx;
-			height: 24rpx;
-			margin-left: auto;
+			width: 32rpx;
+			height: 32rpx;
 		}
 	}
 }
+
 .logout-container {
-	position: fixed;
-	bottom: 40rpx;
-	left: 50%;
-	transform: translateX(-50%);
-	width: 90%;
-}
+	margin-top: 60rpx;
+	padding: 0 30rpx;
 
-.logout-button {
-	width: 100%;
-	height: 80rpx;
-	background-color: $gray-ccc;
-	color: $gray-333;
-	border-radius: 8rpx;
-	font-size: 32rpx;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-	box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.1);
+	.logout-btn {
+		width: 100%;
+		height: 88rpx;
+		line-height: 88rpx;
+		background: #ff5a5f;
+		color: #fff;
+		font-size: 32rpx;
+		border-radius: 48rpx;
+		border: none;
+
+		&:active {
+			opacity: 0.9;
+		}
+	}
 }
 </style>

+ 15 - 0
app/wx-app/src/utils/image.ts

@@ -0,0 +1,15 @@
+/**
+ * 将图片转换为Base64格式
+ * @param filePath 图片临时路径
+ * @returns Promise对象,包含转换后的base64字符串
+ */
+export const convertImageToBase64 = (filePath: string): Promise<string> => {
+	return new Promise((resolve, reject) => {
+		uni.getFileSystemManager().readFile({
+			filePath,
+			encoding: 'base64',
+			success: (res) => resolve(res.data as string),
+			fail: (err) => reject(err),
+		})
+	})
+}

+ 3 - 3
src_0nline/ShwasherSys/ShwasherSys.Application/Invoice/OrderStickBillsApplicationService.cs

@@ -432,11 +432,11 @@ namespace ShwasherSys.Invoice
             var work = ExcelHelper.CreateWorkBook07(path);
             var sheet1 = work.GetSheet("Worksheet");
             sheet1.GenerateCell(4, 4).SetCellValue(customerInfo.CustomerName);
-            sheet1.GenerateCell(4, 12).SetCellValue(bill.SendAddress);
+            sheet1.GenerateCell(4, 14).SetCellValue(bill.SendAddress);
             sheet1.GenerateCell(5, 4).SetCellValue(bill.ContactTels);
-            sheet1.GenerateCell(5, 12).SetCellValue(bill.ContactMan);
+            sheet1.GenerateCell(5, 14).SetCellValue(bill.ContactMan);
             sheet1.GenerateCell(6, 4).SetCellValue(input.Id);
-            sheet1.GenerateCell(6, 9).SetCellValue("日期:" + DateTime.Now.ToString("yyyy年MM月dd日"));
+            sheet1.GenerateCell(6, 11).SetCellValue("日期:" + DateTime.Now.ToString("yyyy年MM月dd日"));
             if (orderSends.Count>1)
             {
                 sheet1.InsertRows(8, orderSends.Count-1);

BIN
src_0nline/ShwasherSys/ShwasherSys.Web/Download/Excel/InvoiceBill/对账单-250218092008.xlsx


BIN
src_0nline/ShwasherSys/ShwasherSys.Web/Download/Excel/InvoiceBill/对账单-250218092131.xlsx


BIN
src_0nline/ShwasherSys/ShwasherSys.Web/Download/Excel/InvoiceBill/对账单-250218092649.xlsx


BIN
src_0nline/ShwasherSys/ShwasherSys.Web/Download/Excel/InvoiceBill/对账单-250219100626.xlsx


+ 5 - 4
src_0nline/ShwasherSys/ShwasherSys.Web/Views/ProductionInfo/ProductionOrderMg.cshtml

@@ -244,7 +244,7 @@ new SelectListItem{Text = @"去料加工",Value = "2"},
                 var rows = config.table.bootstrapTable("getSelections");
                 if (rows.length === 1)
                 {
-                    console.log(rows[0].productionOrderStatus);
+                    console.log(rows[0]);
                     if (rows[0].isLock == 'Y')
                     {
                         abp.message.warn("排产单已删除,不可进行更改!");
@@ -263,12 +263,12 @@ new SelectListItem{Text = @"去料加工",Value = "2"},
                     } else {
                         $(".type2").css("display", "block");
                         var no = rows[0].productionOrderNo.substr(2, 1).toUpperCase();
-                        var type1 = "GHIJKLMNOPQRT";
-                        rows[0].productionType = "0";
+                        var type1 = "GHWJKLMNOPQRT";
+                        //rows[0].productionType = "0";
                         $(".type0").css("display", "block");
                         $(".type1").css("display", "none");
                         if (no && type1.indexOf(no) > -1) {
-                            rows[0].productionType = "1";
+                            //rows[0].productionType = "1";
                             $(".type1").css("display", "block");
                             $(".type0").css("display", "none");
                         }
@@ -281,6 +281,7 @@ new SelectListItem{Text = @"去料加工",Value = "2"},
                         success: function(res) {
 
                             var data = rows[0];
+                            console.log('data---',data)
                             if (res) {
                                 data.model = res.model;
                                 data.partNo = res.partNo;