فهرست منبع

库存信息基本调整完成

Huanyi 7 ساعت پیش
والد
کامیت
cf7a95042b

+ 25 - 0
api/erp/goodsStock.js

@@ -0,0 +1,25 @@
+import request from '@/utils/request';
+
+/**
+ * 分页查询成品库存列表
+ * @param {Object} query - { pageNum, pageSize, clientId, ... }
+ */
+export function getGoodsStockPage(query) {
+	return request({
+		url: '/erp/goodsStock/page',
+		method: 'GET',
+		params: query
+	});
+}
+
+/**
+ * 汇总分页查询:按型号+客户名称分组,SUM(重量)、SUM(支数)
+ * @param {Object} query - { pageNum, pageSize, clientId }
+ */
+export function getGoodsStockSummaryPage(query) {
+	return request({
+		url: '/system/goodsStock/summary/page',
+		method: 'GET',
+		params: query
+	});
+}

+ 11 - 0
api/erp/order.js

@@ -69,6 +69,17 @@ export function cancelOrder(rowId) {
   })
 }
 
+/**
+ * 加急订单
+ * @Author: Trae
+ */
+export function markUrgent(rowId) {
+  return request({
+    url: '/erp/order/urgent/' + rowId,
+    method: 'post'
+  })
+}
+
 /**
  * 查询审核记录
  * @Author: Antigravity

+ 3 - 1
api/resource/oss.js

@@ -1,6 +1,8 @@
 import request from '@/utils/request';
 
-const BASE_URL = 'http://127.0.0.1:8080';
+// const BASE_URL = 'http://127.0.0.1:8080';
+// const BASE_URL = 'http://192.168.1.205:8080';
+const BASE_URL = 'https://app.jxhsal.com/api';
 const CLIENT_ID = 'e48ac397bff4f031b14d6e671eee49c3';
 
 /**

+ 7 - 0
api/system/employee.js

@@ -13,3 +13,10 @@ export function getMyInfo() {
 export function updateMyInfo(data) {
 	return request({ url: '/system/employee/updateProfile', method: 'PUT', data });
 }
+
+/**
+ * 修改密码
+ */
+export function resetPassword(data) {
+	return request({ url: '/system/employee/resetPassword', method: 'PUT', data });
+}

+ 2 - 5
json/orderStatus.json

@@ -1,9 +1,6 @@
 {
   "0": { "text": "待确认", "color": "#FF9900" },
   "1": { "text": "已确认", "color": "#1890FF" },
-  "2": { "text": "已审核", "color": "#52C41A" },
-  "3": { "text": "已签批", "color": "#722ED1" },
-  "4": { "text": "挤压完成", "color": "#13C2C2" },
-  "5": { "text": "生产完成", "color": "#2F54EB" },
-  "6": { "text": "已取消", "color": "#F5222D" }
+  "2": { "text": "挤压完成", "color": "#13C2C2" },
+  "3": { "text": "生产完成", "color": "#2F54EB" }
 }

+ 8 - 0
pages.json

@@ -40,6 +40,10 @@
 			"path": "pages/mine/settings/index",
 			"style": { "navigationStyle": "custom" }
 		},
+		{
+			"path": "pages/mine/settings/resetPassword/index",
+			"style": { "navigationStyle": "custom" }
+		},
 		{
 			"path": "pages/mine/agreement/index",
 			"style": { "navigationStyle": "custom" }
@@ -60,6 +64,10 @@
 			"path": "pages/mine/complaint/detail/index",
 			"style": { "navigationStyle": "custom" }
 		},
+		{
+			"path": "pages/mine/goodsStock/index",
+			"style": { "navigationStyle": "custom", "enablePullDownRefresh": false }
+		},
 		{
 			"path": "pages/mine/index",
 			"style": { "navigationStyle": "custom" }

+ 374 - 0
pages/mine/goodsStock/index.vue

@@ -0,0 +1,374 @@
+<template>
+	<view class="goods-stock-page">
+		<erp-nav-bar title="库存信息" />
+
+		<!-- 客户分类标签 -->
+		<scroll-view scroll-x class="client-tabs" :show-scrollbar="false" :scroll-with-animation="true"
+			:scroll-into-view="'ctab-' + currentTab">
+			<view class="client-tabs-box">
+				<view v-for="(tab, index) in clientTabs" :key="index" :id="'ctab-' + index" class="client-tab-item"
+					:class="{ active: currentTab === index }" @click="switchTab(index)">
+					<text class="client-tab-txt">{{ tab.label }}</text>
+				</view>
+			</view>
+		</scroll-view>
+
+		<!-- 库存列表滚动区 -->
+		<scroll-view scroll-y class="stock-scroll-view" :style="{ height: scrollHeight }" @scrolltolower="onReachEnd"
+			:refresher-enabled="true" :refresher-triggered="refresherTriggered" @refresherrefresh="onPullDownRefresh"
+			:show-scrollbar="false">
+
+			<view class="stock-list-inner">
+				<view class="stock-card" v-for="(item, index) in displayList" :key="index">
+					<view class="stock-card-head">
+						<!-- 全部:客户名称为主标题;锁定客户:型号为主标题 -->
+						<view class="stock-model-info" v-if="currentTab === 0">
+							<text class="stock-model">{{ item.clientName || '-' }}</text>
+							<text class="stock-client" v-if="item.saleCode">{{ item.saleCode }}</text>
+						</view>
+						<view class="stock-model-info" v-else>
+							<text class="stock-model">{{ item.saleCode }}</text>
+							<text class="stock-client">{{ item.clientName || '-' }}</text>
+						</view>
+					</view>
+					<view class="stock-card-body">
+						<view class="stock-info-row">
+							<text class="stock-label">支数</text>
+							<text class="stock-value highlight">{{ item.sumQty != null ? item.sumQty : '-' }} 支</text>
+						</view>
+						<view class="stock-info-row">
+							<text class="stock-label">重量</text>
+							<text class="stock-value">{{ item.sumWt != null ? Number(item.sumWt).toFixed(2) + ' kg' :
+								'-' }}</text>
+						</view>
+					</view>
+				</view>
+
+				<!-- 加载提示 -->
+				<view class="list-status-info" v-if="displayList.length > 0">
+					<view class="loading-wrap" v-if="loading">
+						<view class="load-dot"></view><text>加载中...</text>
+					</view>
+					<view class="nomore-wrap" v-if="noMore">
+						<text class="nomore-line"></text>
+						<text class="nomore-text">已加载全部数据</text>
+						<text class="nomore-line"></text>
+					</view>
+				</view>
+
+				<!-- 缺省态 -->
+				<view class="empty-state" v-if="displayList.length === 0 && !loading">
+					<image src="https://img.icons8.com/clouds/200/open-box.png" mode="aspectFit"></image>
+					<text>暂无库存记录</text>
+				</view>
+
+				<view class="safe-bottom"></view>
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+import ErpNavBar from '@/components/erp-nav-bar.vue';
+import { getGoodsStockSummaryPage } from '@/api/erp/goodsStock.js';
+import { getMyInfo } from '@/api/system/employee.js';
+import { getClientByIds } from '@/api/erp/client.js';
+
+export default {
+	components: { ErpNavBar },
+	data() {
+		return {
+			statusBarHeight: 20,
+			navBarHeight: 44,
+			currentTab: 0,
+			loading: false,
+			noMore: false,
+			refresherTriggered: false,
+			pageNum: 1,
+			pageSize: 10,
+			clientTabs: [{ label: '全部', clientId: '' }],
+			displayList: []
+		}
+	},
+	computed: {
+		scrollHeight() {
+			return `calc(100vh - ${this.statusBarHeight + this.navBarHeight + 40}px)`;
+		}
+	},
+	onLoad() {
+		const winInfo = uni.getWindowInfo ? uni.getWindowInfo() : uni.getSystemInfoSync();
+		this.statusBarHeight = winInfo.statusBarHeight;
+		this.loadClientTabs();
+	},
+	methods: {
+		async loadClientTabs() {
+			try {
+				const res = await getMyInfo();
+				const employee = res.data;
+				if (employee && employee.authClientFRowIDs) {
+					const ids = employee.authClientFRowIDs.split(',').map(s => s.trim()).filter(Boolean);
+					if (ids.length > 0) {
+						const clientRes = await getClientByIds(ids.join(','));
+						const clients = clientRes.data || [];
+						const tabs = [{ label: '全部', clientId: '' }];
+						clients.forEach(c => {
+							tabs.push({ label: c.name || c.num || '-', clientId: c.frowId || c.rowId || '' });
+						});
+						this.clientTabs = tabs;
+					}
+				}
+			} catch (e) {
+				console.error('加载授权客户失败', e);
+			}
+			this.refresh();
+		},
+		switchTab(i) {
+			this.currentTab = i;
+			this.refresh();
+		},
+		refresh() {
+			this.displayList = [];
+			this.noMore = false;
+			this.pageNum = 1;
+			this.loadData();
+		},
+		onPullDownRefresh() {
+			this.refresherTriggered = true;
+			this.refresh();
+			setTimeout(() => { this.refresherTriggered = false; }, 500);
+		},
+		onReachEnd() {
+			if (!this.loading && !this.noMore) this.loadData();
+		},
+		async loadData() {
+			if (this.loading || this.noMore) return;
+			this.loading = true;
+			try {
+				const currentClient = this.clientTabs[this.currentTab];
+				const params = {
+					pageNum: this.pageNum,
+					pageSize: this.pageSize
+				};
+				if (currentClient && currentClient.clientId) {
+					params.clientId = currentClient.clientId;
+				}
+				const res = await getGoodsStockSummaryPage(params);
+				const rows = res.rows || [];
+
+				this.displayList = [...this.displayList, ...rows];
+				this.pageNum++;
+				this.noMore = rows.length === 0 || this.displayList.length >= (res.total || 0);
+			} catch (e) {
+				console.error('加载库存列表失败', e);
+				uni.showToast({ title: e || '加载失败', icon: 'none' });
+			} finally {
+				this.loading = false;
+			}
+		}
+	}
+}
+</script>
+
+<style scoped>
+.goods-stock-page {
+	width: 100vw;
+	height: 100vh;
+	background: #f7f8fa;
+	display: flex;
+	flex-direction: column;
+	overflow: hidden;
+}
+
+/* ========== 客户标签栏 ========== */
+.client-tabs {
+	flex-shrink: 0;
+	background: #fff;
+	border-bottom: 1rpx solid #f0f0f0;
+	white-space: nowrap;
+}
+
+.client-tabs-box {
+	display: flex;
+	padding: 0 20rpx;
+	height: 80rpx;
+	align-items: center;
+	gap: 10rpx;
+}
+
+.client-tab-item {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	padding: 0 28rpx;
+	height: 56rpx;
+	border-radius: 28rpx;
+	background: #f5f6f7;
+	flex-shrink: 0;
+	transition: all 0.2s;
+}
+
+.client-tab-item.active {
+	background: #C1001C;
+}
+
+.client-tab-txt {
+	font-size: 26rpx;
+	color: #666;
+}
+
+.client-tab-item.active .client-tab-txt {
+	color: #fff;
+	font-weight: 600;
+}
+
+/* ========== 滚动列表区 ========== */
+.stock-scroll-view {
+	width: 100%;
+	flex: 1;
+}
+
+.stock-list-inner {
+	padding: 20rpx 30rpx;
+}
+
+/* ========== 库存卡片 ========== */
+.stock-card {
+	background: #fff;
+	border-radius: 20rpx;
+	padding: 30rpx;
+	margin-bottom: 20rpx;
+	box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.03);
+}
+
+.stock-card-head {
+	display: flex;
+	justify-content: space-between;
+	align-items: flex-start;
+	margin-bottom: 24rpx;
+	padding-bottom: 20rpx;
+	border-bottom: 1rpx solid #f5f5f5;
+}
+
+.stock-model-info {
+	display: flex;
+	flex-direction: column;
+	gap: 6rpx;
+}
+
+.stock-model {
+	font-size: 30rpx;
+	font-weight: bold;
+	color: #1a1a1a;
+}
+
+.stock-client {
+	font-size: 24rpx;
+	color: #999;
+}
+
+.stock-card-body {
+	display: flex;
+	flex-direction: column;
+	gap: 16rpx;
+}
+
+.stock-info-row {
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+}
+
+.stock-label {
+	font-size: 26rpx;
+	color: #999;
+}
+
+.stock-value {
+	font-size: 26rpx;
+	color: #333;
+	font-weight: 500;
+}
+
+.stock-value.highlight {
+	color: #C1001C;
+	font-weight: bold;
+	font-size: 30rpx;
+}
+
+/* ========== 加载状态 ========== */
+.list-status-info {
+	padding: 30rpx 0;
+}
+
+.loading-wrap {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	gap: 16rpx;
+	font-size: 26rpx;
+	color: #aaa;
+}
+
+.load-dot {
+	width: 12rpx;
+	height: 12rpx;
+	border-radius: 50%;
+	background: #ccc;
+	animation: dot-blink 1s infinite;
+}
+
+@keyframes dot-blink {
+
+	0%,
+	100% {
+		opacity: 0.3;
+	}
+
+	50% {
+		opacity: 1;
+	}
+}
+
+.nomore-wrap {
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	gap: 16rpx;
+}
+
+.nomore-line {
+	width: 60rpx;
+	height: 1rpx;
+	background: #e0e0e0;
+}
+
+.nomore-text {
+	font-size: 24rpx;
+	color: #ccc;
+}
+
+/* ========== 空状态 ========== */
+.empty-state {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+	padding: 120rpx 0;
+}
+
+.empty-state image {
+	width: 160rpx;
+	height: 160rpx;
+	margin-bottom: 30rpx;
+	opacity: 0.5;
+}
+
+.empty-state text {
+	font-size: 28rpx;
+	color: #bbb;
+}
+
+.safe-bottom {
+	height: 60rpx;
+}
+</style>

+ 8 - 5
pages/mine/index.vue

@@ -100,12 +100,13 @@ export default {
 			employeeInfo: null,
 			servicePhone: '13888888888',
 			orderStates: [
-				{ label: '待审核', tabIndex: 2, icon: assets.minePendingReview },
-				{ label: '待签批', tabIndex: 4, icon: assets.minePendingSign },
-				{ label: '生产中', tabIndex: 5, icon: assets.mineProducing },
-				{ label: '已完成', tabIndex: 6, icon: assets.mineCompleted }
+				{ label: '待确认', tabIndex: 1, icon: assets.minePendingReview },
+				{ label: '已确认', tabIndex: 2, icon: assets.minePendingSign },
+				{ label: '挤压完成', tabIndex: 3, icon: assets.mineProducing },
+				{ label: '生产完成', tabIndex: 4, icon: assets.mineCompleted }
 			],
 			menuList: [
+				{ label: '库存信息', icon: assets.mineStock, id: 'stock' },
 				{ label: '用户协议', icon: assets.mineProtocol, id: 'agreement' },
 				{ label: '隐私政策', icon: assets.minePrivacy, id: 'privacy' },
 				{ label: '投诉与建议', icon: assets.mineComplaint, id: 'complaint' },
@@ -184,7 +185,9 @@ export default {
 		},
 		// 新增:菜单点击处理
 		handleMenuClick(menu) {
-			if (menu.id === 'agreement') {
+			if (menu.id === 'stock') {
+				uni.navigateTo({ url: '/pages/mine/goodsStock/index' });
+			} else if (menu.id === 'agreement') {
 				uni.navigateTo({ url: '/pages/mine/agreement/index' });
 			} else if (menu.id === 'privacy') {
 				uni.navigateTo({ url: '/pages/mine/privacy/index' });

+ 14 - 0
pages/mine/settings/index.vue

@@ -36,6 +36,15 @@
 			</view>
 		</view>
 
+		<view class="settings-list mt-30">
+			<view class="item-row" @click="goResetPassword">
+				<text class="item-label">修改密码</text>
+				<view class="item-right">
+					<text class="icon-more"></text>
+				</view>
+			</view>
+		</view>
+
 		<!-- 授权客户列表 -->
 		<view class="section-card" style="margin-top: 30rpx;">
 			<view class="section-header">
@@ -169,6 +178,11 @@ export default {
 					}
 				}
 			});
+		},
+		goResetPassword() {
+			uni.navigateTo({
+				url: '/pages/mine/settings/resetPassword/index'
+			});
 		}
 	}
 }

+ 143 - 0
pages/mine/settings/resetPassword/index.vue

@@ -0,0 +1,143 @@
+<template>
+    <view class="reset-pwd-root">
+        <erp-nav-bar title="修改密码" />
+
+        <view class="pwd-form">
+            <view class="form-item">
+                <text class="form-label">旧密码</text>
+                <input class="form-input" type="password" v-model="oldPassword" placeholder="请输入旧密码" password />
+            </view>
+
+            <view class="form-item">
+                <text class="form-label">新密码</text>
+                <input class="form-input" type="password" v-model="newPassword" placeholder="请输入新密码" password />
+            </view>
+
+            <view class="form-item">
+                <text class="form-label">确认密码</text>
+                <input class="form-input" type="password" v-model="confirmPassword" placeholder="请再次输入新密码" password />
+            </view>
+        </view>
+
+        <view class="submit-area">
+            <view class="submit-btn" :class="{ disabled: submitting }" @click="doSubmit">
+                <text>{{ submitting ? '提交中...' : '确认修改' }}</text>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+import ErpNavBar from '@/components/erp-nav-bar.vue';
+import { resetPassword } from '@/api/system/employee.js';
+
+export default {
+    components: { ErpNavBar },
+    data() {
+        return {
+            oldPassword: '',
+            newPassword: '',
+            confirmPassword: '',
+            submitting: false
+        }
+    },
+    methods: {
+        async doSubmit() {
+            if (!this.oldPassword) {
+                uni.showToast({ title: '请输入旧密码', icon: 'none' });
+                return;
+            }
+            if (!this.newPassword) {
+                uni.showToast({ title: '请输入新密码', icon: 'none' });
+                return;
+            }
+            if (this.newPassword.length < 6) {
+                uni.showToast({ title: '新密码长度不能少于6位', icon: 'none' });
+                return;
+            }
+            if (this.newPassword !== this.confirmPassword) {
+                uni.showToast({ title: '两次输入的新密码不一致', icon: 'none' });
+                return;
+            }
+            this.submitting = true;
+            try {
+                await resetPassword({
+                    oldPassword: this.oldPassword,
+                    newPassword: this.newPassword
+                });
+                uni.showToast({ title: '密码修改成功', icon: 'success' });
+                setTimeout(() => {
+                    uni.navigateBack();
+                }, 1200);
+            } catch (e) {
+                uni.showToast({ title: e || '修改失败', icon: 'none' });
+            } finally {
+                this.submitting = false;
+            }
+        }
+    }
+}
+</script>
+
+<style scoped>
+.reset-pwd-root {
+    width: 100vw;
+    height: 100vh;
+    background: #F4F6F9;
+    display: flex;
+    flex-direction: column;
+}
+
+.pwd-form {
+    background: #fff;
+    margin: 20rpx 24rpx 0;
+    border-radius: 20rpx;
+    padding: 0 36rpx;
+    box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.02);
+}
+
+.form-item {
+    display: flex;
+    align-items: center;
+    min-height: 104rpx;
+    border-bottom: 1rpx solid #F0F0F3;
+}
+
+.form-item:last-child {
+    border-bottom: none;
+}
+
+.form-label {
+    font-size: 30rpx;
+    color: #1A1A2E;
+    font-weight: 500;
+    width: 160rpx;
+    flex-shrink: 0;
+}
+
+.form-input {
+    flex: 1;
+    font-size: 28rpx;
+    color: #1A1A2E;
+}
+
+.submit-area {
+    padding: 60rpx 60rpx 0;
+}
+
+.submit-btn {
+    height: 88rpx;
+    border-radius: 20rpx;
+    background: linear-gradient(135deg, #C1001C 0%, #E8553D 100%);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #fff;
+    font-size: 32rpx;
+    font-weight: 600;
+}
+
+.submit-btn.disabled {
+    opacity: 0.6;
+}
+</style>

+ 100 - 29
pages/order/detail/index.vue

@@ -6,7 +6,12 @@
 		<view class="status-banner-container" :class="order.statusType" id="nav-header">
 			<view class="status-banner-content">
 				<view class="header-main">
-					<text class="status-title">{{ order.statusName }}</text>
+					<view class="header-title-row">
+						<text class="status-title">{{ order.statusName }}</text>
+						<view class="urgent-badge" v-if="order.isUrgent">
+							<text>加急</text>
+						</view>
+					</view>
 					<text class="status-sub">{{ statusSubText }}</text>
 				</view>
 				<view class="header-icon-wrap">
@@ -26,8 +31,10 @@
 						</view>
 						<view class="data-item"><text class="l">型号名称</text><text class="v">{{ model.typeName ||
 							'铝型材主料' }}</text></view>
-						<view class="data-item"><text class="l">单据编号</text><text class="v">{{ model.docCode || '-' }}</text></view>
-						<view class="data-item"><text class="l">项目号</text><text class="v">{{ model.itemNo || '-' }}</text></view>
+						<view class="data-item"><text class="l">单据编号</text><text class="v">{{ model.docCode || '-'
+						}}</text></view>
+						<view class="data-item"><text class="l">项目号</text><text class="v">{{ model.itemNo || '-'
+						}}</text></view>
 						<view class="data-item"><text class="l">型材材质</text><text class="v">{{ model.material ||
 							'6063-T5' }}</text></view>
 						<view class="line-split"></view>
@@ -42,6 +49,11 @@
 							'1.2' }} mm</text></view>
 						<view class="data-item"><text class="l">需求支数</text><text class="v highlight">{{ model.count }}
 								支</text></view>
+						<view class="line-split"></view>
+						<view class="data-item"><text class="l">挤压入库数</text><text class="v">{{ model.semiInQty != null ?
+							model.semiInQty : '-' }}</text></view>
+						<view class="data-item"><text class="l">成品入库数</text><text class="v">{{ model.goodsInQty != null
+							? model.goodsInQty : '-' }}</text></view>
 					</view>
 				</view>
 
@@ -49,8 +61,9 @@
 				<view class="data-group-card shadow-less">
 					<view class="card-head">订单详情</view>
 					<view class="data-item"><text class="l">订单单号</text><text class="v selectable">{{ order.orderNo
-							}}</text></view>
-					<view class="data-item"><text class="l">单据编号</text><text class="v selectable">{{ order.docCode || '-' }}</text></view>
+					}}</text></view>
+					<view class="data-item"><text class="l">单据编号</text><text class="v selectable">{{ order.docCode ||
+						'-' }}</text></view>
 					<view class="data-item"><text class="l">下单日期</text><text class="v">{{ order.time }}</text></view>
 					<view class="data-item"><text class="l">支付方式</text><text class="v">月结扣款</text></view>
 				</view>
@@ -62,6 +75,9 @@
 
 		<!-- 3. 底部固定操作栏 -->
 		<view class="detail-action-bar-fixed" id="footer-bar">
+			<view class="action-btn-wrap" v-if="!order.isUrgent && order.isConfirmed !== null">
+				<button class="action-btn urgency" @click="doMarkUrgent">加急订单</button>
+			</view>
 			<view class="action-btn-wrap single" v-if="order.isConfirmed === 0">
 				<button class="action-btn primary" @click="callSales">呼叫业务员</button>
 			</view>
@@ -75,7 +91,7 @@
 
 <script>
 import ErpNavBar from '@/components/erp-nav-bar.vue';
-import { getOrderDetail } from '@/api/erp/order.js';
+import { getOrderDetail, markUrgent } from '@/api/erp/order.js';
 import { getPhone } from '@/api/system/phone.js';
 export default {
 	components: { ErpNavBar },
@@ -89,7 +105,9 @@ export default {
 			order: {
 				orderNo: '-',
 				docCode: '',
-				isConfirmed: 1,
+				isConfirmed: null,
+				isUrgent: false,
+				status: null,
 				statusName: '加载中',
 				statusType: 'pending',
 				models: [],
@@ -103,11 +121,8 @@ export default {
 			const map = {
 				pending: '您的订单已提交,正在等待管理端同步确认中...',
 				finish: '订单已确认,并已成功同步到 ERP 系统中。',
-				approved: '订单已在 ERP 系统中审核通过。',
-				reviewed: '订单已由相关负责人签批。',
 				exFinished: '订单关联的产品型材已挤压完成。',
-				productionFinish: '订单所含产品型材已全部生产完成!',
-				cancelled: '该订单已被撤销。'
+				productionFinish: '订单所含产品型材已全部生产完成!'
 			};
 			return map[this.order.statusType] || '订单状态更新中';
 		},
@@ -141,11 +156,8 @@ export default {
 				const statusMap = {
 					0: { name: '待确认', type: 'pending' },
 					1: { name: '已确认', type: 'finish' },
-					2: { name: '已审核', type: 'approved' },
-					3: { name: '已签批', type: 'reviewed' },
-					4: { name: '挤压完成', type: 'exFinished' },
-					5: { name: '生产完成', type: 'productionFinish' },
-					6: { name: '已取消', type: 'cancelled' }
+					2: { name: '挤压完成', type: 'exFinished' },
+					3: { name: '生产完成', type: 'productionFinish' }
 				};
 				const s = statusMap[data.status] || { name: '待确认', type: 'pending' };
 
@@ -154,6 +166,8 @@ export default {
 					docCode: data.docCode || '',
 					rowId: data.rowId,
 					isConfirmed: data.isConfirmed,
+					isUrgent: data.urgentFlag === 1,
+					status: data.status,
 					statusName: s.name,
 					statusType: s.type,
 					time: data.createTime || '-',
@@ -168,7 +182,9 @@ export default {
 						package: d.packName || '普通包装',
 						length: d.length ? Number(d.length).toFixed(4) : '0',
 						wallThickness: d.wallThickness ? Number(d.wallThickness).toFixed(4) : '1.2',
-						count: d.count || 0
+						count: d.count || 0,
+						goodsInQty: d.goodsInQty,
+						semiInQty: d.semiInQty
 					}))
 				};
 			} catch (e) {
@@ -182,6 +198,26 @@ export default {
 
 		callSales() { uni.makePhoneCall({ phoneNumber: this.salesPhone }); },
 		goHome() { uni.reLaunch({ url: '/pages/order/index' }); },
+		doMarkUrgent() {
+			uni.showModal({
+				title: '加急确认',
+				content: '确认将该订单标记为加急吗?',
+				confirmColor: '#FF6600',
+				success: async (res) => {
+					if (!res.confirm) return;
+					try {
+						uni.showLoading({ title: '处理中' });
+						await markUrgent(this.order.rowId);
+						uni.hideLoading();
+						this.order.isUrgent = true;
+						uni.showToast({ title: '已标记为加急订单', icon: 'success' });
+					} catch (e) {
+						uni.hideLoading();
+						uni.showToast({ title: e || '操作失败', icon: 'none' });
+					}
+				}
+			});
+		},
 		async loadPhone() {
 			try {
 				const res = await getPhone();
@@ -228,14 +264,6 @@ export default {
 	background: linear-gradient(135deg, #1890FF 0%, #69C0FF 100%);
 }
 
-.status-banner-container.approved {
-	background: linear-gradient(135deg, #52C41A 0%, #95DE64 100%);
-}
-
-.status-banner-container.reviewed {
-	background: linear-gradient(135deg, #722ED1 0%, #B37FEB 100%);
-}
-
 .status-banner-container.exFinished {
 	background: linear-gradient(135deg, #13C2C2 0%, #5CDBD3 100%);
 }
@@ -244,10 +272,6 @@ export default {
 	background: linear-gradient(135deg, #2F54EB 0%, #85A5FF 100%);
 }
 
-.status-banner-container.cancelled {
-	background: linear-gradient(135deg, #F5222D 0%, #FF7875 100%);
-}
-
 /* 状态横幅内容 */
 .status-banner-content {
 	padding: 40rpx;
@@ -268,6 +292,46 @@ export default {
 	margin-bottom: 12rpx;
 }
 
+.header-title-row {
+	display: flex;
+	align-items: center;
+	gap: 16rpx;
+	margin-bottom: 12rpx;
+}
+
+.header-title-row .status-title {
+	margin-bottom: 0;
+}
+
+.urgent-badge {
+	display: flex;
+	align-items: center;
+	padding: 6rpx 18rpx;
+	background: rgba(255, 255, 255, 0.25);
+	border: 2rpx solid rgba(255, 255, 255, 0.6);
+	border-radius: 8rpx;
+	animation: urgent-pulse 1.5s ease-in-out infinite;
+}
+
+.urgent-badge text {
+	font-size: 22rpx;
+	color: #fff;
+	font-weight: 700;
+	letter-spacing: 2rpx;
+}
+
+@keyframes urgent-pulse {
+
+	0%,
+	100% {
+		opacity: 1;
+	}
+
+	50% {
+		opacity: 0.6;
+	}
+}
+
 .status-sub {
 	font-size: 26rpx;
 	opacity: 0.9;
@@ -398,6 +462,13 @@ export default {
 	font-weight: normal;
 }
 
+.action-btn.urgency {
+	background: #C1001C;
+	color: #fff;
+	border: none;
+	margin-bottom: 16rpx;
+}
+
 .safe-area-bottom-support {
 	height: constant(safe-area-inset-bottom);
 	height: env(safe-area-inset-bottom);

+ 120 - 25
pages/order/list/index.vue

@@ -10,6 +10,17 @@
 			<text class="cs-name">{{ clientName }}</text>
 		</view>
 
+		<!-- 型号搜索栏 -->
+		<view class="model-search-bar">
+			<view class="ms-input-wrap">
+				<image class="ms-icon" src="https://img.icons8.com/ios/50/999999/search--v1.png" mode="aspectFit">
+				</image>
+				<input class="ms-input" v-model="modelNum" placeholder="搜索型号(如:GR-TK9011)" @confirm="onModelSearch"
+					confirm-type="search" />
+				<text class="ms-clear" v-if="modelNum" @click="clearModelSearch">×</text>
+			</view>
+		</view>
+
 		<!-- 2. 分类切换:使用 scroll-view 滚动,彻底释放所有综合状态 -->
 		<scroll-view scroll-x class="tabs-fixed" :show-scrollbar="false" :scroll-with-animation="true"
 			:scroll-into-view="'tab-' + currentTab">
@@ -35,7 +46,12 @@
 			<view class="order-list-inner">
 				<view class="order-card" v-for="(item, index) in displayList" :key="index" @click="goDetail(item)">
 					<view class="card-head">
-						<text class="order-id">单号:{{ item.orderNo }}</text>
+						<view class="card-head-left">
+							<text class="order-id">单号:{{ item.orderNo }}</text>
+							<view class="urgent-tag" v-if="item.isUrgent">
+								<text>加急</text>
+							</view>
+						</view>
 						<view class="status-badge" :class="item.statusType">{{ item.statusName }}</view>
 					</view>
 					<view class="card-body">
@@ -59,6 +75,8 @@
 					<view class="card-foot">
 						<text class="time">{{ item.time }}</text>
 						<view class="btns">
+							<view class="btn-view urgency" v-if="!item.isUrgent" @click.stop="doMarkUrgent(item)">加急
+							</view>
 							<view class="btn-view primary" @click.stop="goDetail(item)">订单详情</view>
 						</view>
 					</view>
@@ -97,7 +115,7 @@
 import ErpTabBar from '@/components/erp-tab-bar.vue';
 import ErpNavBar from '@/components/erp-nav-bar.vue';
 import ErpSubmitBar from '@/components/erp-submit-bar.vue';
-import { listMyOrder, listOrderByClientId } from '@/api/erp/order.js';
+import { listMyOrder, listOrderByClientId, markUrgent } from '@/api/erp/order.js';
 export default {
 	components: { ErpTabBar, ErpNavBar, ErpSubmitBar },
 	data() {
@@ -110,9 +128,10 @@ export default {
 			noMore: false,
 			refresherTriggered: false,
 			pageNum: 1,
-			tabs: ['全部', '待确认', '已确认', '已审核', '已签批', '挤压完成', '生产完成', '已取消'],
+			tabs: ['全部', '待确认', '已确认', '挤压完成', '生产完成'],
 			clientId: '',
 			clientName: '',
+			modelNum: '',
 			allOrders: [],
 			displayList: []
 		}
@@ -120,7 +139,8 @@ export default {
 	computed: {
 		scrollHeight() {
 			const clientBarH = this.clientName ? 35 : 0;
-			return `calc(100vh - ${this.statusBarHeight + this.navBarHeight + this.tabBarHeight + clientBarH}px)`;
+			const searchBarH = 50;
+			return `calc(100vh - ${this.statusBarHeight + this.navBarHeight + this.tabBarHeight + clientBarH + searchBarH}px)`;
 		}
 	},
 	onLoad(options) {
@@ -146,6 +166,8 @@ export default {
 			});
 		},
 		refresh() { this.displayList = []; this.noMore = false; this.pageNum = 1; this.loadData(); },
+		onModelSearch() { this.refresh(); },
+		clearModelSearch() { this.modelNum = ''; this.refresh(); },
 		onReachEnd() { if (!this.loading && !this.noMore) this.loadData(); },
 		async loadData() {
 			if (this.loading || this.noMore) return;
@@ -158,8 +180,11 @@ export default {
 				if (this.clientId) {
 					params.clientId = this.clientId;
 				}
+				if (this.modelNum) {
+					params.modelNum = this.modelNum;
+				}
 				if (this.currentTab > 0) {
-					const indexToStatus = [undefined, 0, 1, 2, 3, 4, 5, 6];
+					const indexToStatus = [undefined, 0, 1, 2, 3];
 					params.status = indexToStatus[this.currentTab];
 				}
 				const res = this.clientId
@@ -171,11 +196,8 @@ export default {
 					const statusMap = {
 						0: { name: '待确认', type: 'pending' },
 						1: { name: '已确认', type: 'finish' },
-						2: { name: '已审核', type: 'approved' },
-						3: { name: '已签批', type: 'reviewed' },
-						4: { name: '挤压完成', type: 'exFinished' },
-						5: { name: '生产完成', type: 'productionFinish' },
-						6: { name: '已取消', type: 'cancelled' }
+						2: { name: '挤压完成', type: 'exFinished' },
+						3: { name: '生产完成', type: 'productionFinish' }
 					};
 					const s = statusMap[item.status] || { name: '待确认', type: 'pending' };
 
@@ -185,6 +207,7 @@ export default {
 						status: item.status,
 						statusName: s.name,
 						statusType: s.type,
+						isUrgent: item.urgentFlag === 1,
 						time: item.createTime,
 						totalCount: item.totalCount || 0,
 						models: (item.details || []).map(d => ({
@@ -211,6 +234,26 @@ export default {
 				url: `/pages/order/detail/index?rowId=${item.rowId}`
 			});
 		},
+		async doMarkUrgent(item) {
+			uni.showModal({
+				title: '加急确认',
+				content: '确认将该订单标记为加急吗?',
+				confirmColor: '#FF6600',
+				success: async (res) => {
+					if (!res.confirm) return;
+					try {
+						uni.showLoading({ title: '处理中' });
+						await markUrgent(item.rowId);
+						uni.hideLoading();
+						item.isUrgent = true;
+						uni.showToast({ title: '已标记为加急订单', icon: 'success' });
+					} catch (e) {
+						uni.hideLoading();
+						uni.showToast({ title: e || '操作失败', icon: 'none' });
+					}
+				}
+			});
+		},
 		goCreateOrder() {
 			let url = '/pages/order/index';
 			if (this.clientId) {
@@ -316,6 +359,44 @@ export default {
 	background: linear-gradient(180deg, rgba(193, 0, 28, 0.03) 0%, transparent 100%);
 }
 
+/* ========== 型号搜索栏 ========== */
+.model-search-bar {
+	background: #fff;
+	padding: 12rpx 30rpx;
+	flex-shrink: 0;
+}
+
+.ms-input-wrap {
+	display: flex;
+	align-items: center;
+	background: #f5f6f7;
+	border-radius: 36rpx;
+	padding: 0 24rpx;
+	height: 64rpx;
+}
+
+.ms-icon {
+	width: 32rpx;
+	height: 32rpx;
+	margin-right: 12rpx;
+	flex-shrink: 0;
+	opacity: 0.5;
+}
+
+.ms-input {
+	flex: 1;
+	font-size: 26rpx;
+	color: #333;
+	height: 100%;
+}
+
+.ms-clear {
+	font-size: 32rpx;
+	color: #ccc;
+	padding: 0 10rpx;
+	flex-shrink: 0;
+}
+
 .cs-accent {
 	width: 8rpx;
 	height: 8rpx;
@@ -372,6 +453,29 @@ export default {
 	font-weight: bold;
 }
 
+.card-head-left {
+	display: flex;
+	align-items: center;
+	gap: 12rpx;
+	flex: 1;
+	min-width: 0;
+}
+
+.urgent-tag {
+	display: flex;
+	align-items: center;
+	padding: 4rpx 12rpx;
+	background: linear-gradient(135deg, #FF4D00 0%, #FF8C00 100%);
+	border-radius: 6rpx;
+	flex-shrink: 0;
+}
+
+.urgent-tag text {
+	font-size: 20rpx;
+	color: #fff;
+	font-weight: 700;
+}
+
 .status-badge {
 	font-size: 20rpx;
 	padding: 4rpx 16rpx;
@@ -388,16 +492,6 @@ export default {
 	color: #1890FF;
 }
 
-.status-badge.approved {
-	background: #F6FFED;
-	color: #52C41A;
-}
-
-.status-badge.reviewed {
-	background: #F9F0FF;
-	color: #722ED1;
-}
-
 .status-badge.exFinished {
 	background: #E6FFF9;
 	color: #13C2C2;
@@ -408,11 +502,6 @@ export default {
 	color: #2F54EB;
 }
 
-.status-badge.cancelled {
-	background: #FFF1F0;
-	color: #F5222D;
-}
-
 .card-body {
 	padding: 24rpx 0;
 	border-top: 1rpx dashed #f0f0f0;
@@ -544,6 +633,12 @@ export default {
 	color: #fff;
 }
 
+.btn-view.urgency {
+	background: #C1001C;
+	color: #fff;
+	border: none;
+}
+
 .list-status-info {
 	padding: 40rpx 0;
 	display: flex;

+ 1 - 0
utils/assets.js

@@ -37,4 +37,5 @@ export default {
 	mineArrow: '/static/mine/arrow.png',
 	mineSettings: '/static/mine/settings.png',
 	mineComplaint: '/static/mine/complaint.png',
+	mineStock: '/static/mine/settings.png',
 };

+ 2 - 2
utils/request.js

@@ -1,6 +1,6 @@
-const BASE_URL = 'http://127.0.0.1:8080';
+// const BASE_URL = 'http://127.0.0.1:8080';
 // const BASE_URL = 'http://192.168.1.205:8080';
-// const BASE_URL = 'https://app.jxhsal.com/api';
+const BASE_URL = 'https://app.jxhsal.com/api';
 
 const CLIENT_ID = 'e48ac397bff4f031b14d6e671eee49c3';