实现订单管理核心功能,包括订单创建、查询、取消和状态管理
This commit is contained in:
5191
mini_program/client-mp/package-lock.json
generated
Normal file
5191
mini_program/client-mp/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@dcloudio/uni-app": "^3.0.0-alpha-3070320230701001",
|
||||
"@dcloudio/uni-ui": "^1.5.11",
|
||||
"pinia": "^2.1.0",
|
||||
"vue": "^3.3.0"
|
||||
},
|
||||
@@ -31,4 +32,4 @@
|
||||
"prettier": "^2.0.0",
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<script setup lang="ts">
|
||||
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
onLaunch(() => {
|
||||
console.log('App Launch');
|
||||
// 初始化时检查登录状态
|
||||
userStore.checkLoginStatus();
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
console.log('App Show');
|
||||
});
|
||||
|
||||
onHide(() => {
|
||||
console.log('App Hide');
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view>
|
||||
<!-- 这里是所有页面的容器 -->
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
/* 全局样式 */
|
||||
page {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,
|
||||
Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
50
mini_program/client-mp/src/api/acceptance.ts
Normal file
50
mini_program/client-mp/src/api/acceptance.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { request } from '@/utils/request';
|
||||
import type { IAcceptance, IAcceptanceDetail } from '@/types/acceptance';
|
||||
|
||||
// 获取验收列表
|
||||
export const fetchAcceptanceList = async (): Promise<IAcceptance[]> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/acceptance/list',
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取验收列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取验收详情
|
||||
export const fetchAcceptanceDetail = async (acceptanceId: string): Promise<IAcceptanceDetail> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: `/acceptance/${acceptanceId}/detail`,
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取验收详情失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 提交验收结果
|
||||
export const submitAcceptance = async (data: {
|
||||
orderId: string;
|
||||
result: 'passed' | 'failed';
|
||||
images: string[];
|
||||
note?: string;
|
||||
}): Promise<IAcceptanceDetail> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/acceptance/submit',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('提交验收结果失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
49
mini_program/client-mp/src/api/auth.ts
Normal file
49
mini_program/client-mp/src/api/auth.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { request } from '@/utils/request';
|
||||
interface ILoginForm {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
interface IRegisterForm {
|
||||
username: string;
|
||||
password: string;
|
||||
phone: string;
|
||||
captcha: string;
|
||||
role: 'client' | 'supplier' | 'driver' | 'staff';
|
||||
}
|
||||
|
||||
// 用户登录
|
||||
export const login = async (data: ILoginForm) => {
|
||||
return request({
|
||||
url: '/auth/login',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 用户注册
|
||||
export const register = async (data: IRegisterForm) => {
|
||||
return request({
|
||||
url: '/auth/register',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 获取验证码
|
||||
export const getCaptcha = async (phone: string) => {
|
||||
return request({
|
||||
url: '/auth/captcha',
|
||||
method: 'GET',
|
||||
data: { phone }
|
||||
});
|
||||
};
|
||||
|
||||
// 验证验证码
|
||||
export const verifyCaptcha = async (phone: string, code: string) => {
|
||||
return request({
|
||||
url: '/auth/verify-captcha',
|
||||
method: 'POST',
|
||||
data: { phone, code }
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import { request } from '@/utils/request';
|
||||
import type { IOrder, IOrderStats } from '@/types/order';
|
||||
import type { IOrder, IOrderStats, OrderStatus, ITransportInfo, IOrderCreateForm } from '@/types/order';
|
||||
|
||||
// 获取订单统计
|
||||
export const fetchOrderStats = async (): Promise<IOrderStats> => {
|
||||
@@ -15,6 +15,37 @@ export const fetchOrderStats = async (): Promise<IOrderStats> => {
|
||||
}
|
||||
};
|
||||
|
||||
// 获取订单列表
|
||||
export const fetchOrders = async (
|
||||
status?: OrderStatus | 'all'
|
||||
): Promise<IOrder[]> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/order/list',
|
||||
method: 'GET',
|
||||
data: status === 'all' ? undefined : { status }
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取订单列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取订单详情
|
||||
export const fetchOrderDetail = async (orderId: string): Promise<IOrder> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: `/order/${orderId}/detail`,
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取订单详情失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取最近订单
|
||||
export const fetchRecentOrders = async (): Promise<IOrder[]> => {
|
||||
try {
|
||||
@@ -27,4 +58,45 @@ export const fetchRecentOrders = async (): Promise<IOrder[]> => {
|
||||
console.error('获取最近订单失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 取消订单
|
||||
export const cancelOrder = async (orderId: string): Promise<void> => {
|
||||
try {
|
||||
await request({
|
||||
url: `/order/${orderId}/cancel`,
|
||||
method: 'POST'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('取消订单失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 确认收货
|
||||
export const acceptOrder = async (orderId: string): Promise<void> => {
|
||||
try {
|
||||
await request({
|
||||
url: `/order/${orderId}/accept`,
|
||||
method: 'POST'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('确认收货失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 创建订单
|
||||
export const createOrder = async (form: IOrderCreateForm): Promise<IOrder> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/order/create',
|
||||
method: 'POST',
|
||||
data: form
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('创建订单失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
65
mini_program/client-mp/src/api/payment.ts
Normal file
65
mini_program/client-mp/src/api/payment.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { request } from '@/utils/request';
|
||||
import type { IPayment, IPaymentDetail } from '@/types/payment';
|
||||
|
||||
// 获取支付列表
|
||||
export const fetchPaymentList = async (): Promise<IPayment[]> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/payment/list',
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取支付列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取支付详情
|
||||
export const fetchPaymentDetail = async (paymentId: string): Promise<IPaymentDetail> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: `/payment/${paymentId}/detail`,
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取支付详情失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 发起支付
|
||||
export const createPayment = async (orderId: string, amount: number, method: string): Promise<{
|
||||
paymentId: string;
|
||||
paymentParams: any;
|
||||
}> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/payment/create',
|
||||
method: 'POST',
|
||||
data: { orderId, amount, method }
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('创建支付失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 查询支付状态
|
||||
export const checkPaymentStatus = async (paymentId: string): Promise<{
|
||||
status: 'pending' | 'paid' | 'failed';
|
||||
paidTime?: string;
|
||||
}> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: `/payment/${paymentId}/status`,
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('查询支付状态失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
29
mini_program/client-mp/src/api/statistics.ts
Normal file
29
mini_program/client-mp/src/api/statistics.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { request } from '@/utils/request';
|
||||
|
||||
// 获取采购统计数据
|
||||
export const getPurchaseStats = async (params: {
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}) => {
|
||||
return request({
|
||||
url: '/stats/purchase',
|
||||
method: 'GET',
|
||||
data: params
|
||||
});
|
||||
};
|
||||
|
||||
// 获取运输统计数据
|
||||
export const getTransportStats = async () => {
|
||||
return request({
|
||||
url: '/stats/transport',
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
// 获取财务统计数据
|
||||
export const getFinancialStats = async () => {
|
||||
return request({
|
||||
url: '/stats/financial',
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
30
mini_program/client-mp/src/api/supplier.ts
Normal file
30
mini_program/client-mp/src/api/supplier.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { request } from '@/utils/request';
|
||||
import type { ISupplier, ICattleBreed } from '@/types/supplier';
|
||||
|
||||
// 获取供应商列表
|
||||
export const fetchSuppliers = async (): Promise<ISupplier[]> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/supplier/list',
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取供应商列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取牛只品种列表
|
||||
export const fetchCattleBreeds = async (): Promise<ICattleBreed[]> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/supplier/cattle-breeds',
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取牛只品种列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
52
mini_program/client-mp/src/api/tracking.ts
Normal file
52
mini_program/client-mp/src/api/tracking.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { request } from '@/utils/request';
|
||||
|
||||
// 获取运输跟踪列表
|
||||
export const fetchTrackingList = (params?: {
|
||||
status?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}) => {
|
||||
return request({
|
||||
url: '/api/tracking/list',
|
||||
method: 'GET',
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
// 获取运输跟踪详情
|
||||
export const fetchTrackingDetail = (id: string) => {
|
||||
return request({
|
||||
url: `/api/tracking/${id}`,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
// 更新运输状态
|
||||
export const updateTrackingStatus = (data: {
|
||||
id: string;
|
||||
status: string;
|
||||
location?: string;
|
||||
remark?: string;
|
||||
}) => {
|
||||
return request({
|
||||
url: '/api/tracking/update',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 获取运输历史记录
|
||||
export const getTrackingHistory = (id: string) => {
|
||||
return request({
|
||||
url: `/api/tracking/${id}/history`,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
// 订阅实时位置更新
|
||||
export const subscribeTracking = (id: string) => {
|
||||
return request({
|
||||
url: `/api/tracking/${id}/subscribe`,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
51
mini_program/client-mp/src/api/transport.ts
Normal file
51
mini_program/client-mp/src/api/transport.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { request } from '@/utils/request';
|
||||
import type { ITransportDetail, ITransportUpdate } from '@/types/transport';
|
||||
|
||||
// 获取运输详情
|
||||
export const fetchTransportDetail = async (orderId: string): Promise<ITransportDetail> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: `/transport/${orderId}/detail`,
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取运输详情失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 订阅运输更新
|
||||
export const subscribeTransportUpdates = (
|
||||
orderId: string,
|
||||
callback: (update: ITransportUpdate) => void
|
||||
): (() => void) => {
|
||||
// 创建WebSocket连接
|
||||
const ws = uni.connectSocket({
|
||||
url: `wss://api.example.com/transport/${orderId}/updates`,
|
||||
success: () => {
|
||||
console.log('WebSocket连接成功');
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('WebSocket连接失败:', err);
|
||||
}
|
||||
});
|
||||
|
||||
// 监听消息
|
||||
ws.onMessage((res) => {
|
||||
try {
|
||||
const data = JSON.parse(res.data) as ITransportUpdate;
|
||||
callback(data);
|
||||
} catch (error) {
|
||||
console.error('解析运输更新失败:', error);
|
||||
}
|
||||
});
|
||||
|
||||
// 返回取消订阅函数
|
||||
return () => {
|
||||
ws.close({
|
||||
success: () => console.log('WebSocket已关闭'),
|
||||
fail: (err) => console.error('关闭WebSocket失败:', err)
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -1,5 +1,34 @@
|
||||
import { request } from '@/utils/request';
|
||||
import type { IUser } from '@/types/user';
|
||||
import type { IUser, IUserSettings } from '@/types/user';
|
||||
|
||||
// 更新用户设置
|
||||
export const updateUserSettings = async (settings: Partial<IUserSettings>) => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/user/settings',
|
||||
method: 'POST',
|
||||
data: settings
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('更新用户设置失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取用户详细信息(包含个人资料)
|
||||
export const fetchUserProfile = async (): Promise<IUser & { profile: any }> => {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/user/profile',
|
||||
method: 'GET'
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.error('获取用户资料失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取用户信息
|
||||
export const fetchUserInfo = async (): Promise<IUser> => {
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { fetchAcceptanceDetail } from '@/api/acceptance';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const acceptanceDetail = ref<any>(null);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 获取验收详情
|
||||
const getAcceptanceDetail = async (acceptanceId: string) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
acceptanceDetail.value = await fetchAcceptanceDetail(acceptanceId);
|
||||
} catch (err) {
|
||||
error.value = '获取验收详情失败';
|
||||
console.error('获取验收详情失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const acceptanceId = ''; // 从路由参数获取
|
||||
if (acceptanceId) {
|
||||
getAcceptanceDetail(acceptanceId);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 验收详情 -->
|
||||
<view v-if="acceptanceDetail" class="card">
|
||||
<view class="flex-between">
|
||||
<text class="text-bold">订单号: {{ acceptanceDetail.orderId }}</text>
|
||||
<text :class="acceptanceDetail.status === 'passed' ? 'text-primary' : 'text-danger'">
|
||||
{{ acceptanceDetail.status === 'passed' ? '验收通过' : '验收未通过' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
<text>验收时间: {{ acceptanceDetail.acceptanceTime }}</text>
|
||||
<view class="margin-top-sm">
|
||||
<text>验收人: {{ acceptanceDetail.acceptor }}</text>
|
||||
</view>
|
||||
<view class="margin-top-sm">
|
||||
<text>验收结果: {{ acceptanceDetail.result }}</text>
|
||||
</view>
|
||||
<view class="margin-top-sm" v-if="acceptanceDetail.images">
|
||||
<text>验收照片:</text>
|
||||
<!-- 图片展示 -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,70 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { fetchAcceptanceList } from '@/api/acceptance';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const acceptanceList = ref<any[]>([]);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 获取验收列表
|
||||
const getAcceptanceList = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
acceptanceList.value = await fetchAcceptanceList();
|
||||
} catch (err) {
|
||||
error.value = '获取验收列表失败';
|
||||
console.error('获取验收列表失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getAcceptanceList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 验收列表 -->
|
||||
<view v-for="item in acceptanceList" :key="item.id" class="card">
|
||||
<view class="flex-between">
|
||||
<text class="text-bold">订单号: {{ item.orderId }}</text>
|
||||
<text :class="item.status === 'passed' ? 'text-primary' : 'text-danger'">
|
||||
{{ item.status === 'passed' ? '验收通过' : '验收未通过' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
<text>验收时间: {{ item.acceptanceTime }}</text>
|
||||
<view class="margin-top-sm">
|
||||
<text>验收结果: {{ item.result }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
91
mini_program/client-mp/src/pages/auth/login.vue
Normal file
91
mini_program/client-mp/src/pages/auth/login.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { login } from '@/api/auth';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const username = ref('');
|
||||
const password = ref('');
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 登录
|
||||
const handleLogin = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = '';
|
||||
const user = await login(username.value, password.value);
|
||||
userStore.setUser(user);
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success'
|
||||
});
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
} catch (err) {
|
||||
error.value = '用户名或密码错误';
|
||||
console.error('登录失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="card">
|
||||
<text class="text-bold">登录</text>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="margin-top">
|
||||
<text>用户名</text>
|
||||
<input v-model="username" placeholder="请输入用户名" />
|
||||
</view>
|
||||
|
||||
<view class="margin-top">
|
||||
<text>密码</text>
|
||||
<input v-model="password" placeholder="请输入密码" type="password" />
|
||||
</view>
|
||||
|
||||
<button
|
||||
class="margin-top"
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="handleLogin"
|
||||
>
|
||||
登录
|
||||
</button>
|
||||
|
||||
<view class="margin-top text-center">
|
||||
<text>还没有账号?</text>
|
||||
<text class="text-primary" @click="uni.navigateTo({ url: '/pages/auth/register' })">立即注册</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="error" class="text-danger text-center margin-top">
|
||||
{{ error }}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
input {
|
||||
border: 1rpx solid #eee;
|
||||
border-radius: 8rpx;
|
||||
padding: 10rpx;
|
||||
margin-top: 10rpx;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
180
mini_program/client-mp/src/pages/auth/register.vue
Normal file
180
mini_program/client-mp/src/pages/auth/register.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { register, getCaptcha, verifyCaptcha } from '@/api/auth';
|
||||
import { showSuccess, showError } from '@/utils/feedback';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const form = ref({
|
||||
username: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
phone: '',
|
||||
captcha: '',
|
||||
role: 'client'
|
||||
});
|
||||
const captchaSent = ref(false);
|
||||
const countdown = ref(0);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 发送验证码
|
||||
const sendCaptcha = async () => {
|
||||
if (!form.value.phone) {
|
||||
showError('请输入手机号');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await getCaptcha(form.value.phone);
|
||||
captchaSent.value = true;
|
||||
countdown.value = 60;
|
||||
const timer = setInterval(() => {
|
||||
countdown.value--;
|
||||
if (countdown.value <= 0) {
|
||||
clearInterval(timer);
|
||||
captchaSent.value = false;
|
||||
}
|
||||
}, 1000);
|
||||
showSuccess('验证码已发送');
|
||||
} catch (error) {
|
||||
showError('发送验证码失败');
|
||||
console.error('发送验证码失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 提交注册
|
||||
const submitRegister = async () => {
|
||||
if (form.value.password !== form.value.confirmPassword) {
|
||||
showError('两次输入的密码不一致');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = '';
|
||||
const user = await register(form.value);
|
||||
userStore.setUser(user);
|
||||
showSuccess('注册成功');
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
} catch (err) {
|
||||
error.value = '注册失败,请稍后再试';
|
||||
showError('注册失败');
|
||||
console.error('注册失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="card">
|
||||
<text class="text-bold">注册</text>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">用户名</text>
|
||||
<input v-model="form.username" placeholder="请输入用户名" />
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">密码</text>
|
||||
<input v-model="form.password" placeholder="请输入密码" type="password" />
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">确认密码</text>
|
||||
<input v-model="form.confirmPassword" placeholder="请再次输入密码" type="password" />
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">手机号</text>
|
||||
<input v-model="form.phone" placeholder="请输入手机号" type="number" />
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="label">验证码</text>
|
||||
<view class="captcha-input">
|
||||
<input v-model="form.captcha" placeholder="请输入验证码" />
|
||||
<button
|
||||
size="mini"
|
||||
:disabled="captchaSent"
|
||||
@click="sendCaptcha"
|
||||
>
|
||||
{{ captchaSent ? `${countdown}秒后重试` : '获取验证码' }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="submitRegister"
|
||||
>
|
||||
注册
|
||||
</button>
|
||||
|
||||
<view class="login-link">
|
||||
<text>已有账号?</text>
|
||||
<text class="text-primary" @click="uni.navigateTo({ url: '/pages/auth/login' })">立即登录</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="error" class="error-message">
|
||||
{{ error }}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input {
|
||||
border: 1rpx solid #eee;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.captcha-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.login-link {
|
||||
margin-top: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
margin-top: 20rpx;
|
||||
color: #ff3b30;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
263
mini_program/client-mp/src/pages/order/order-create.vue
Normal file
263
mini_program/client-mp/src/pages/order/order-create.vue
Normal file
@@ -0,0 +1,263 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { useSupplierStore } from '@/stores/supplier';
|
||||
import type { IOrderCreateForm, ICattleBreed } from './types';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const supplierStore = useSupplierStore();
|
||||
|
||||
// 表单数据
|
||||
const form = ref<IOrderCreateForm>({
|
||||
supplierId: '',
|
||||
cattleBreed: '',
|
||||
quantity: 1,
|
||||
estimatedWeight: 0,
|
||||
price: 0,
|
||||
prepaymentRatio: 30,
|
||||
notes: ''
|
||||
});
|
||||
|
||||
// 加载供应商和品种数据
|
||||
const loading = ref(false);
|
||||
const loadData = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
await supplierStore.fetchSuppliers();
|
||||
await supplierStore.fetchCattleBreeds();
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '加载数据失败',
|
||||
icon: 'none'
|
||||
});
|
||||
console.error('加载供应商和品种数据失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 计算总金额
|
||||
const totalAmount = computed(() => {
|
||||
return form.value.estimatedWeight * form.value.price;
|
||||
});
|
||||
|
||||
// 计算预付款金额
|
||||
const prepaymentAmount = computed(() => {
|
||||
return totalAmount.value * (form.value.prepaymentRatio / 100);
|
||||
});
|
||||
|
||||
// 提交订单
|
||||
const submitOrder = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
await orderStore.createOrder(form.value);
|
||||
uni.showToast({
|
||||
title: '订单创建成功',
|
||||
icon: 'success'
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '订单创建失败',
|
||||
icon: 'none'
|
||||
});
|
||||
console.error('订单创建失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化加载数据
|
||||
onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 加载状态 -->
|
||||
<view v-if="loading" class="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 创建订单表单 -->
|
||||
<view v-else class="form">
|
||||
<!-- 供应商选择 -->
|
||||
<view class="form-item">
|
||||
<text class="label">选择供应商</text>
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="supplierStore.suppliers"
|
||||
range-key="name"
|
||||
@change="(e) => form.supplierId = supplierStore.suppliers[e.detail.value].id"
|
||||
>
|
||||
<view class="picker">
|
||||
<text v-if="form.supplierId">
|
||||
{{ supplierStore.suppliers.find(s => s.id === form.supplierId)?.name || '请选择供应商' }}
|
||||
</text>
|
||||
<text v-else class="placeholder">请选择供应商</text>
|
||||
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<!-- 牛只品种选择 -->
|
||||
<view class="form-item">
|
||||
<text class="label">牛只品种</text>
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="supplierStore.cattleBreeds"
|
||||
range-key="name"
|
||||
@change="(e) => {
|
||||
form.cattleBreed = supplierStore.cattleBreeds[e.detail.value].name;
|
||||
form.price = supplierStore.cattleBreeds[e.detail.value].price;
|
||||
}"
|
||||
>
|
||||
<view class="picker">
|
||||
<text v-if="form.cattleBreed">
|
||||
{{ form.cattleBreed }} (¥{{ form.price }}/kg)
|
||||
</text>
|
||||
<text v-else class="placeholder">请选择牛只品种</text>
|
||||
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<!-- 数量输入 -->
|
||||
<view class="form-item">
|
||||
<text class="label">数量(头)</text>
|
||||
<input
|
||||
type="number"
|
||||
v-model="form.quantity"
|
||||
placeholder="请输入数量"
|
||||
class="input"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 预估重量 -->
|
||||
<view class="form-item">
|
||||
<text class="label">预估重量(kg)</text>
|
||||
<input
|
||||
type="number"
|
||||
v-model="form.estimatedWeight"
|
||||
placeholder="请输入预估重量"
|
||||
class="input"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 价格显示 -->
|
||||
<view class="form-item">
|
||||
<text class="label">单价</text>
|
||||
<text class="value">¥{{ form.price }}/kg</text>
|
||||
</view>
|
||||
|
||||
<!-- 总金额 -->
|
||||
<view class="form-item">
|
||||
<text class="label">总金额</text>
|
||||
<text class="value">¥{{ totalAmount }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 预付款比例 -->
|
||||
<view class="form-item">
|
||||
<text class="label">预付款比例</text>
|
||||
<slider
|
||||
:value="form.prepaymentRatio"
|
||||
min="0"
|
||||
max="100"
|
||||
show-value
|
||||
activeColor="#3cc51f"
|
||||
@change="e => form.prepaymentRatio = e.detail.value"
|
||||
/>
|
||||
<text class="hint">预付款金额: ¥{{ prepaymentAmount }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 备注 -->
|
||||
<view class="form-item">
|
||||
<text class="label">备注</text>
|
||||
<textarea
|
||||
v-model="form.notes"
|
||||
placeholder="请输入备注信息"
|
||||
class="textarea"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<button
|
||||
type="primary"
|
||||
:disabled="!form.supplierId || !form.cattleBreed || !form.estimatedWeight"
|
||||
@tap="submitOrder"
|
||||
>
|
||||
提交订单
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 40rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.form {
|
||||
.form-item {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 2rpx 12rpx 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
margin-bottom: 20rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.picker {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10rpx 0;
|
||||
|
||||
.placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
border: 1rpx solid #eee;
|
||||
padding: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #3cc51f;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hint {
|
||||
display: block;
|
||||
margin-top: 10rpx;
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
border: 1rpx solid #eee;
|
||||
padding: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
332
mini_program/client-mp/src/pages/order/order-detail.vue
Normal file
332
mini_program/client-mp/src/pages/order/order-detail.vue
Normal file
@@ -0,0 +1,332 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import type { IOrder } from '@/types/order';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const loading = ref(false);
|
||||
const orderId = ref('');
|
||||
const order = ref<IOrder | null>(null);
|
||||
|
||||
// 获取路由参数
|
||||
onLoad((options) => {
|
||||
orderId.value = options.id || '';
|
||||
loadOrderDetail();
|
||||
});
|
||||
|
||||
// 加载订单详情
|
||||
const loadOrderDetail = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
await orderStore.fetchOrderDetail(orderId.value);
|
||||
order.value = orderStore.currentOrder;
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '加载订单详情失败',
|
||||
icon: 'none'
|
||||
});
|
||||
console.error('加载订单详情失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 订单状态颜色
|
||||
const statusColor = computed(() => {
|
||||
if (!order.value) return '';
|
||||
switch (order.value.status) {
|
||||
case 'pending':
|
||||
return 'warning';
|
||||
case 'confirmed':
|
||||
return 'primary';
|
||||
case 'in_transit':
|
||||
return 'primary';
|
||||
case 'pending_acceptance':
|
||||
return 'warning';
|
||||
case 'completed':
|
||||
return 'success';
|
||||
case 'canceled':
|
||||
return 'gray';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
// 取消订单
|
||||
const handleCancelOrder = async () => {
|
||||
try {
|
||||
await orderStore.cancelOrder(orderId.value);
|
||||
order.value = orderStore.currentOrder;
|
||||
uni.showToast({
|
||||
title: '订单已取消',
|
||||
icon: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '取消订单失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 确认收货
|
||||
const handleAcceptOrder = async () => {
|
||||
try {
|
||||
await orderStore.acceptOrder(orderId.value);
|
||||
order.value = orderStore.currentOrder;
|
||||
uni.showToast({
|
||||
title: '订单已确认收货',
|
||||
icon: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '确认收货失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 加载中 -->
|
||||
<view v-if="loading" class="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 订单详情 -->
|
||||
<view v-if="order" class="order-detail">
|
||||
<!-- 订单状态 -->
|
||||
<view class="status-card" :class="`status-${order.status}`">
|
||||
<text class="status-text">{{ order.statusText }}</text>
|
||||
<text class="status-desc" v-if="order.statusDesc">
|
||||
{{ order.statusDesc }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<view class="card">
|
||||
<view class="section-title">
|
||||
<text class="text-bold">订单信息</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">订单编号:</text>
|
||||
<text class="info-value">{{ order.orderNo }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">创建时间:</text>
|
||||
<text class="info-value">{{ order.createTime }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">更新时间:</text>
|
||||
<text class="info-value">{{ order.updateTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 供应商信息 -->
|
||||
<view class="card">
|
||||
<view class="section-title">
|
||||
<text class="text-bold">供应商信息</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">供应商名称:</text>
|
||||
<text class="info-value">{{ order.supplierName }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">联系人:</text>
|
||||
<text class="info-value">{{ order.supplierContact }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">联系电话:</text>
|
||||
<text class="info-value">{{ order.supplierPhone }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 牛只信息 -->
|
||||
<view class="card">
|
||||
<view class="section-title">
|
||||
<text class="text-bold">牛只信息</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">品种:</text>
|
||||
<text class="info-value">{{ order.cattleBreed }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">数量:</text>
|
||||
<text class="info-value">{{ order.quantity }}头</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">总重量:</text>
|
||||
<text class="info-value">{{ order.weight }}kg</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">单价:</text>
|
||||
<text class="info-value">¥{{ order.price }}/kg</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">总金额:</text>
|
||||
<text class="info-value">¥{{ order.totalAmount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 运输信息 -->
|
||||
<view v-if="order.transportInfo" class="card">
|
||||
<view class="section-title">
|
||||
<text class="text-bold">运输信息</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">司机姓名:</text>
|
||||
<text class="info-value">{{ order.transportInfo.driverName }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">司机电话:</text>
|
||||
<text class="info-value">{{ order.transportInfo.driverPhone }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">车牌号:</text>
|
||||
<text class="info-value">{{ order.transportInfo.licensePlate }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">预计到达:</text>
|
||||
<text class="info-value">{{ order.transportInfo.estimatedArrival }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="action-buttons">
|
||||
<button
|
||||
v-if="order.status === 'pending'"
|
||||
type="warn"
|
||||
@tap="handleCancelOrder"
|
||||
>
|
||||
取消订单
|
||||
</button>
|
||||
<button
|
||||
v-if="order.status === 'pending_acceptance'"
|
||||
type="primary"
|
||||
@tap="handleAcceptOrder"
|
||||
>
|
||||
确认收货
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-if="!loading && !order" class="empty">
|
||||
<image src="/static/images/empty-order.png" mode="aspectFit"></image>
|
||||
<text class="empty-text">订单不存在</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 40rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.status-card {
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
|
||||
.status-text {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-desc {
|
||||
display: block;
|
||||
margin-top: 10rpx;
|
||||
font-size: 24rpx;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&.status-pending {
|
||||
background-color: #ff9900;
|
||||
}
|
||||
|
||||
&.status-confirmed {
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
&.status-in_transit {
|
||||
background-color: #1989fa;
|
||||
}
|
||||
|
||||
&.status-pending_acceptance {
|
||||
background-color: #ff9900;
|
||||
}
|
||||
|
||||
&.status-completed {
|
||||
background-color: #3cc51f;
|
||||
}
|
||||
|
||||
&.status-canceled {
|
||||
background-color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
.section-title {
|
||||
padding-bottom: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
margin-bottom: 15rpx;
|
||||
|
||||
.info-label {
|
||||
width: 150rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-top: 40rpx;
|
||||
|
||||
button {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
|
||||
image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
301
mini_program/client-mp/src/pages/order/order-list.vue
Normal file
301
mini_program/client-mp/src/pages/order/order-list.vue
Normal file
@@ -0,0 +1,301 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import uniIcons from '@dcloudio/uni-ui/lib/uni-icons/uni-icons.vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import type { IOrder, OrderStatus } from '@/types/order';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const UniIcons = uniIcons;
|
||||
const loading = ref(false);
|
||||
const refreshing = ref(false);
|
||||
const statusFilter = ref<OrderStatus | 'all'>('all');
|
||||
|
||||
// 获取订单列表
|
||||
const loadOrders = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
await orderStore.fetchOrders(statusFilter.value);
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '加载订单失败',
|
||||
icon: 'none'
|
||||
});
|
||||
console.error('加载订单列表失败:', error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
refreshing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = () => {
|
||||
refreshing.value = true;
|
||||
loadOrders();
|
||||
};
|
||||
|
||||
// 初始化加载
|
||||
onMounted(() => {
|
||||
loadOrders();
|
||||
});
|
||||
|
||||
// 过滤后的订单列表
|
||||
const filteredOrders = computed(() => {
|
||||
if (statusFilter.value === 'all') {
|
||||
return orderStore.orders;
|
||||
}
|
||||
return orderStore.orders.filter(
|
||||
order => order.status === statusFilter.value
|
||||
);
|
||||
});
|
||||
|
||||
// 跳转到订单详情
|
||||
const navigateToDetail = (id: string) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/order/order-detail?id=${id}`
|
||||
});
|
||||
};
|
||||
|
||||
// 跳转到创建订单
|
||||
const navigateToCreate = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/order/order-create'
|
||||
});
|
||||
};
|
||||
|
||||
// 订单状态选项
|
||||
const statusOptions = [
|
||||
{ value: 'all', label: '全部订单' },
|
||||
{ value: 'pending', label: '待确认' },
|
||||
{ value: 'confirmed', label: '已确认' },
|
||||
{ value: 'in_transit', label: '运输中' },
|
||||
{ value: 'pending_acceptance', label: '待验收' },
|
||||
{ value: 'completed', label: '已完成' },
|
||||
{ value: 'canceled', label: '已取消' }
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 筛选栏 -->
|
||||
<view class="filter-bar">
|
||||
<picker
|
||||
mode="selector"
|
||||
:range="statusOptions"
|
||||
range-key="label"
|
||||
@change="(e) => statusFilter = statusOptions[e.detail.value].value"
|
||||
>
|
||||
<view class="filter-item">
|
||||
<text>{{ statusOptions.find(opt => opt.value === statusFilter)?.label }}</text>
|
||||
<uni-icons type="arrowdown" size="16" color="#666"></uni-icons>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<scroll-view
|
||||
scroll-y
|
||||
refresher-enabled
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
>
|
||||
<!-- 空状态 -->
|
||||
<view v-if="!loading && filteredOrders.length === 0" class="empty">
|
||||
<image src="/static/images/empty-order.png" mode="aspectFit"></image>
|
||||
<text class="empty-text">暂无订单</text>
|
||||
<button
|
||||
type="button"
|
||||
size="mini"
|
||||
class="empty-btn primary"
|
||||
@tap="navigateToCreate"
|
||||
>
|
||||
创建订单
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<view
|
||||
v-for="order in filteredOrders"
|
||||
:key="order.id"
|
||||
class="order-item"
|
||||
@tap="navigateToDetail(order.id)"
|
||||
>
|
||||
<view class="order-header">
|
||||
<text class="order-no">订单号: {{ order.orderNo }}</text>
|
||||
<text :class="`status-${order.status}`">
|
||||
{{ order.statusText }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="order-content">
|
||||
<view class="order-info">
|
||||
<text>供应商: {{ order.supplierName }}</text>
|
||||
<text>数量: {{ order.quantity }}头</text>
|
||||
</view>
|
||||
<view class="order-info">
|
||||
<text>重量: {{ order.weight }}kg</text>
|
||||
<text>金额: ¥{{ order.totalAmount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-footer">
|
||||
<text class="order-time">{{ order.createTime }}</text>
|
||||
<view class="order-actions">
|
||||
<button
|
||||
v-if="order.status === 'pending'"
|
||||
size="mini"
|
||||
type="button"
|
||||
class="warn"
|
||||
@tap.stop="orderStore.cancelOrder(order.id)"
|
||||
>
|
||||
取消订单
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<view v-if="loading" class="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 创建订单按钮 -->
|
||||
<view class="create-btn">
|
||||
<button type="button" class="primary" @tap="navigateToCreate">
|
||||
<uni-icons type="plus" size="20" color="#fff"></uni-icons>
|
||||
创建订单
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
height: 100vh;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.filter-bar {
|
||||
background-color: #fff;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 2rpx 12rpx 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.order-item {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx 0 rgba(0, 0, 0, 0.1);
|
||||
|
||||
.order-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
|
||||
.order-no {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.status-pending {
|
||||
color: #ff9900;
|
||||
}
|
||||
|
||||
.status-confirmed {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.status-in_transit {
|
||||
color: #1989fa;
|
||||
}
|
||||
|
||||
.status-pending_acceptance {
|
||||
color: #ff9900;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
color: #3cc51f;
|
||||
}
|
||||
|
||||
.status-canceled {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.order-content {
|
||||
padding: 20rpx 0;
|
||||
|
||||
.order-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.order-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-top: 20rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
|
||||
.order-time {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
|
||||
image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
color: #999;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 20rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.create-btn {
|
||||
position: fixed;
|
||||
bottom: 40rpx;
|
||||
right: 40rpx;
|
||||
z-index: 999;
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
box-shadow: 0 4rpx 12rpx 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
18
mini_program/client-mp/src/pages/order/types.ts
Normal file
18
mini_program/client-mp/src/pages/order/types.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// 创建订单表单类型
|
||||
export interface IOrderCreateForm {
|
||||
supplierId: string;
|
||||
cattleBreed: string;
|
||||
quantity: number;
|
||||
estimatedWeight: number;
|
||||
price: number;
|
||||
prepaymentRatio: number;
|
||||
notes: string;
|
||||
}
|
||||
|
||||
// 牛只品种类型
|
||||
export interface ICattleBreed {
|
||||
id: string;
|
||||
name: string;
|
||||
price: number;
|
||||
description?: string;
|
||||
}
|
||||
79
mini_program/client-mp/src/pages/payment/payment-detail.vue
Normal file
79
mini_program/client-mp/src/pages/payment/payment-detail.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { fetchPaymentDetail } from '@/api/payment';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const paymentDetail = ref<any>(null);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 获取支付详情
|
||||
const getPaymentDetail = async (paymentId: string) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
paymentDetail.value = await fetchPaymentDetail(paymentId);
|
||||
} catch (err) {
|
||||
error.value = '获取支付详情失败';
|
||||
console.error('获取支付详情失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const paymentId = ''; // 从路由参数获取
|
||||
if (paymentId) {
|
||||
getPaymentDetail(paymentId);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 支付详情 -->
|
||||
<view v-if="paymentDetail" class="card">
|
||||
<view class="flex-between">
|
||||
<text class="text-bold">订单号: {{ paymentDetail.orderId }}</text>
|
||||
<text :class="paymentDetail.status === 'paid' ? 'text-primary' : 'text-warning'">
|
||||
{{ paymentDetail.status === 'paid' ? '已支付' : '待支付' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
<text>金额: ¥{{ paymentDetail.amount }}</text>
|
||||
<view class="margin-top-sm">
|
||||
<text>支付方式: {{ paymentDetail.paymentMethod }}</text>
|
||||
</view>
|
||||
<view class="margin-top-sm" v-if="paymentDetail.status === 'paid'">
|
||||
<text>支付时间: {{ paymentDetail.paidTime }}</text>
|
||||
</view>
|
||||
<view class="margin-top-sm">
|
||||
<button type="primary" v-if="paymentDetail.status === 'pending'">立即支付</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
70
mini_program/client-mp/src/pages/payment/payment-list.vue
Normal file
70
mini_program/client-mp/src/pages/payment/payment-list.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { fetchPaymentList } from '@/api/payment';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const paymentList = ref<any[]>([]);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 获取支付列表
|
||||
const getPaymentList = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
paymentList.value = await fetchPaymentList();
|
||||
} catch (err) {
|
||||
error.value = '获取支付列表失败';
|
||||
console.error('获取支付列表失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getPaymentList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 支付列表 -->
|
||||
<view v-for="item in paymentList" :key="item.id" class="card">
|
||||
<view class="flex-between">
|
||||
<text class="text-bold">订单号: {{ item.orderId }}</text>
|
||||
<text :class="item.status === 'paid' ? 'text-primary' : 'text-warning'">
|
||||
{{ item.status === 'paid' ? '已支付' : '待支付' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
<text>金额: ¥{{ item.amount }}</text>
|
||||
<view class="margin-top-sm">
|
||||
<text>支付方式: {{ item.paymentMethod }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
96
mini_program/client-mp/src/pages/statistics/statistics.vue
Normal file
96
mini_program/client-mp/src/pages/statistics/statistics.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { getPurchaseStats, getTransportStats, getFinancialStats } from '@/api/statistics';
|
||||
|
||||
const statistics = ref<any>(null);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 获取统计数据
|
||||
const getStatistics = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const [purchase, transport, financial] = await Promise.all([
|
||||
getPurchaseStats(),
|
||||
getTransportStats(),
|
||||
getFinancialStats()
|
||||
]);
|
||||
statistics.value = {
|
||||
...purchase,
|
||||
...transport,
|
||||
...financial
|
||||
};
|
||||
} catch (err) {
|
||||
error.value = '获取统计数据失败';
|
||||
console.error('获取统计数据失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getStatistics();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 统计数据 -->
|
||||
<view v-if="statistics" class="card">
|
||||
<text class="text-bold">采购统计</text>
|
||||
<view class="divider"></view>
|
||||
<view class="flex-between margin-top-sm">
|
||||
<text>总采购量: {{ statistics.totalPurchase }}头</text>
|
||||
<text>总金额: ¥{{ statistics.totalAmount }}</text>
|
||||
</view>
|
||||
<view class="flex-between margin-top-sm">
|
||||
<text>平均价格: ¥{{ statistics.averagePrice }}/头</text>
|
||||
<text>平均重量: {{ statistics.averageWeight }}kg</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 图表区域 -->
|
||||
<view class="card margin-top">
|
||||
<text class="text-bold">采购趋势</text>
|
||||
<view class="divider"></view>
|
||||
<!-- 这里将集成图表组件 -->
|
||||
<view class="chart-placeholder">
|
||||
<text>采购趋势图表</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.chart-placeholder {
|
||||
height: 300rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
</style>
|
||||
111
mini_program/client-mp/src/pages/tracking/tracking-detail.vue
Normal file
111
mini_program/client-mp/src/pages/tracking/tracking-detail.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import {
|
||||
fetchTrackingDetail,
|
||||
updateTrackingStatus,
|
||||
subscribeTracking
|
||||
} from '@/api/tracking';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const trackingDetail = ref<any>(null);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 获取运输详情
|
||||
const getTrackingDetail = async (trackingId: string) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
trackingDetail.value = await fetchTrackingDetail(trackingId);
|
||||
} catch (err) {
|
||||
error.value = '获取运输详情失败';
|
||||
console.error('获取运输详情失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const trackingId = ''; // 从路由参数获取
|
||||
if (trackingId) {
|
||||
getTrackingDetail(trackingId);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 运输详情 -->
|
||||
<view v-if="trackingDetail" class="card">
|
||||
<view class="flex-between">
|
||||
<text class="text-bold">订单号: {{ trackingDetail.orderId }}</text>
|
||||
<text :class="trackingDetail.status === 'completed' ? 'text-primary' : 'text-warning'">
|
||||
{{ trackingDetail.status === 'completed' ? '已完成' : '运输中' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="margin-top-sm">
|
||||
<text>司机: {{ trackingDetail.driverName }}</text>
|
||||
</view>
|
||||
|
||||
<view class="margin-top-sm">
|
||||
<text>联系电话: {{ trackingDetail.driverPhone }}</text>
|
||||
</view>
|
||||
|
||||
<view class="margin-top-sm">
|
||||
<text>当前位置: {{ trackingDetail.currentLocation }}</text>
|
||||
</view>
|
||||
|
||||
<view class="margin-top-sm">
|
||||
<text>预计到达: {{ trackingDetail.estimatedArrival }}</text>
|
||||
</view>
|
||||
|
||||
<view class="margin-top-sm">
|
||||
<text>已行驶距离: {{ trackingDetail.distanceTraveled }}公里</text>
|
||||
</view>
|
||||
|
||||
<view class="margin-top-sm">
|
||||
<text>剩余距离: {{ trackingDetail.remainingDistance }}公里</text>
|
||||
</view>
|
||||
|
||||
<!-- 地图容器 -->
|
||||
<view class="map-container margin-top">
|
||||
<text>地图显示区域</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.map-container {
|
||||
height: 300rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
</style>
|
||||
73
mini_program/client-mp/src/pages/tracking/tracking-list.vue
Normal file
73
mini_program/client-mp/src/pages/tracking/tracking-list.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { fetchTrackingList } from '@/api/tracking';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const trackingList = ref<any[]>([]);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 获取运输跟踪列表
|
||||
const getTrackingList = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
trackingList.value = await fetchTrackingList();
|
||||
} catch (err) {
|
||||
error.value = '获取运输跟踪列表失败';
|
||||
console.error('获取运输跟踪列表失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getTrackingList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 运输跟踪列表 -->
|
||||
<view v-for="item in trackingList" :key="item.id" class="card">
|
||||
<view class="flex-between">
|
||||
<text class="text-bold">订单号: {{ item.orderId }}</text>
|
||||
<text :class="item.status === 'completed' ? 'text-primary' : 'text-warning'">
|
||||
{{ item.status === 'completed' ? '已完成' : '运输中' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
<text>司机: {{ item.driverName }}</text>
|
||||
<view class="margin-top-sm">
|
||||
<text>当前位置: {{ item.currentLocation }}</text>
|
||||
</view>
|
||||
<view class="margin-top-sm">
|
||||
<text>预计到达: {{ item.estimatedArrival }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
148
mini_program/client-mp/src/pages/transport/transport-track.vue
Normal file
148
mini_program/client-mp/src/pages/transport/transport-track.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, computed } from 'vue';
|
||||
import { useOrderStore } from '@/stores/order';
|
||||
import { fetchTransportDetail, subscribeTransportUpdates } from '@/api/transport';
|
||||
import type { ITransportDetail } from '@/types/transport';
|
||||
|
||||
const orderStore = useOrderStore();
|
||||
const transportDetail = ref<ITransportDetail | null>(null);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
const isSubscribed = ref(false);
|
||||
|
||||
// 获取运输详情
|
||||
const getTransportDetail = async (orderId: string) => {
|
||||
try {
|
||||
loading.value = true;
|
||||
transportDetail.value = await fetchTransportDetail(orderId);
|
||||
subscribeToUpdates(orderId);
|
||||
} catch (err) {
|
||||
error.value = '获取运输信息失败';
|
||||
console.error('获取运输信息失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 订阅运输更新
|
||||
const subscribeToUpdates = (orderId: string) => {
|
||||
if (isSubscribed.value) return;
|
||||
|
||||
const unsubscribe = subscribeTransportUpdates(orderId, (update) => {
|
||||
if (transportDetail.value) {
|
||||
transportDetail.value = { ...transportDetail.value, ...update };
|
||||
}
|
||||
});
|
||||
|
||||
isSubscribed.value = true;
|
||||
|
||||
onUnmounted(() => {
|
||||
unsubscribe();
|
||||
isSubscribed.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
// 计算预计到达时间
|
||||
const eta = computed(() => {
|
||||
if (!transportDetail.value) return '--';
|
||||
const { distance, speed } = transportDetail.value;
|
||||
if (!distance || !speed) return '计算中...';
|
||||
|
||||
const hours = distance / speed;
|
||||
const now = new Date();
|
||||
now.setHours(now.getHours() + hours);
|
||||
|
||||
return `${hours.toFixed(1)}小时 (${now.getHours()}:${now.getMinutes().toString().padStart(2, '0')})`;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const orderId = orderStore.currentOrder?.id;
|
||||
if (orderId) {
|
||||
getTransportDetail(orderId);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 地图容器 -->
|
||||
<view class="map-container">
|
||||
<!-- 这里将集成地图组件 -->
|
||||
<text v-if="!transportDetail">加载地图中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 运输信息概览 -->
|
||||
<view class="card" v-if="transportDetail">
|
||||
<view class="flex-between">
|
||||
<text class="text-bold">运输状态: {{ transportDetail.statusText }}</text>
|
||||
<text class="text-primary">预计到达: {{ eta }}</text>
|
||||
</view>
|
||||
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="flex-between margin-top-sm">
|
||||
<text>当前位置: {{ transportDetail.currentLocation }}</text>
|
||||
<text>已行驶: {{ transportDetail.distanceTraveled }}公里</text>
|
||||
</view>
|
||||
|
||||
<view class="flex-between margin-top-sm">
|
||||
<text>司机: {{ transportDetail.driverName }}</text>
|
||||
<text>联系电话: {{ transportDetail.driverPhone }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 牛只状态 -->
|
||||
<view class="card margin-top" v-if="transportDetail">
|
||||
<text class="text-bold">牛只状态监控</text>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="flex-row margin-top-sm" v-for="(cattle, index) in transportDetail.cattleStatus" :key="index">
|
||||
<text>牛只 {{ index + 1 }}:</text>
|
||||
<text :class="['margin-left-sm', cattle.status === 'normal' ? 'text-primary' : 'text-danger']">
|
||||
{{ cattle.statusText }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 异常预警 -->
|
||||
<view class="card margin-top" v-if="transportDetail?.hasWarning">
|
||||
<text class="text-bold text-danger">异常预警</text>
|
||||
<view class="divider"></view>
|
||||
<text>{{ transportDetail.warningMessage }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
height: 400rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
</style>
|
||||
101
mini_program/client-mp/src/pages/user/profile.vue
Normal file
101
mini_program/client-mp/src/pages/user/profile.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { fetchUserProfile } from '@/api/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const profile = ref<any>(null);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 获取用户信息
|
||||
const getUserProfile = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
profile.value = await fetchUserProfile();
|
||||
} catch (err) {
|
||||
error.value = '获取用户信息失败';
|
||||
console.error('获取用户信息失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 退出登录
|
||||
const handleLogout = () => {
|
||||
userStore.clearUser();
|
||||
uni.redirectTo({
|
||||
url: '/pages/auth/login'
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getUserProfile();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 用户信息 -->
|
||||
<view class="card" v-if="profile">
|
||||
<view class="flex-center">
|
||||
<image
|
||||
:src="profile.avatar || '/static/default-avatar.png'"
|
||||
mode="aspectFill"
|
||||
class="avatar"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="margin-top">
|
||||
<text class="text-bold">用户名: {{ profile.username }}</text>
|
||||
</view>
|
||||
|
||||
<view class="margin-top">
|
||||
<text>手机号: {{ profile.phone }}</text>
|
||||
</view>
|
||||
|
||||
<view class="margin-top">
|
||||
<text>注册时间: {{ profile.createdAt }}</text>
|
||||
</view>
|
||||
|
||||
<button
|
||||
class="margin-top"
|
||||
type="warn"
|
||||
@click="handleLogout"
|
||||
>
|
||||
退出登录
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view class="flex-center" v-if="loading">
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 错误信息 -->
|
||||
<view class="flex-center" v-if="error">
|
||||
<text class="text-danger">{{ error }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 150rpx;
|
||||
height: 150rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
91
mini_program/client-mp/src/pages/user/settings.vue
Normal file
91
mini_program/client-mp/src/pages/user/settings.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { updateUserSettings } from '@/api/user';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const settings = ref({
|
||||
notification: true,
|
||||
darkMode: false,
|
||||
language: 'zh-CN'
|
||||
});
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
|
||||
// 保存设置
|
||||
const saveSettings = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
await updateUserSettings(settings.value);
|
||||
uni.showToast({
|
||||
title: '设置已保存',
|
||||
icon: 'success'
|
||||
});
|
||||
} catch (err) {
|
||||
error.value = '保存设置失败';
|
||||
console.error('保存设置失败:', err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="card">
|
||||
<text class="text-bold">系统设置</text>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="setting-item">
|
||||
<text>消息通知</text>
|
||||
<switch :checked="settings.notification" @change="(e: any) => settings.notification = e.detail.value" />
|
||||
</view>
|
||||
|
||||
<view class="setting-item">
|
||||
<text>深色模式</text>
|
||||
<switch :checked="settings.darkMode" @change="(e: any) => settings.darkMode = e.detail.value" />
|
||||
</view>
|
||||
|
||||
<view class="setting-item">
|
||||
<text>语言设置</text>
|
||||
<picker mode="selector" :range="['简体中文', 'English']">
|
||||
<text>{{ settings.language === 'zh-CN' ? '简体中文' : 'English' }}</text>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<button
|
||||
class="margin-top"
|
||||
type="primary"
|
||||
:loading="loading"
|
||||
@click="saveSettings"
|
||||
>
|
||||
保存设置
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<view v-if="error" class="text-danger text-center margin-top">
|
||||
{{ error }}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.setting-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,17 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref } from 'vue';
|
||||
import type { IOrder, IOrderStats } from '@/types/order';
|
||||
import { fetchOrderStats, fetchRecentOrders } from '@/api/order';
|
||||
import type { IOrder, IOrderStats, OrderStatus, ITransportInfo, IOrderCreateForm } from '@/types/order';
|
||||
import type { ITransportDetail } from '@/types/transport';
|
||||
import {
|
||||
fetchOrderStats,
|
||||
fetchRecentOrders,
|
||||
fetchOrders,
|
||||
fetchOrderDetail,
|
||||
createOrder,
|
||||
cancelOrder,
|
||||
acceptOrder
|
||||
} from '@/api/order';
|
||||
import { fetchTransportDetail } from '@/api/transport';
|
||||
|
||||
export const useOrderStore = defineStore('order', () => {
|
||||
// 订单统计
|
||||
@@ -13,9 +23,15 @@ export const useOrderStore = defineStore('order', () => {
|
||||
const totalWeight = ref(0);
|
||||
const averagePrice = ref(0);
|
||||
|
||||
// 订单列表
|
||||
const orders = ref<IOrder[]>([]);
|
||||
|
||||
// 最近订单
|
||||
const recentOrders = ref<IOrder[]>([]);
|
||||
|
||||
// 当前查看的订单详情
|
||||
const currentOrder = ref<IOrder | null>(null);
|
||||
|
||||
// 获取订单统计
|
||||
const fetchOrderStats = async () => {
|
||||
try {
|
||||
@@ -33,17 +49,125 @@ export const useOrderStore = defineStore('order', () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 获取订单列表
|
||||
const fetchOrders = async (status?: OrderStatus | 'all') => {
|
||||
try {
|
||||
const ordersData = await fetchOrders(status);
|
||||
orders.value = ordersData;
|
||||
} catch (error) {
|
||||
console.error('获取订单列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取订单详情
|
||||
const fetchOrderDetail = async (orderId: string) => {
|
||||
try {
|
||||
const order = await fetchOrderDetail(orderId);
|
||||
currentOrder.value = order;
|
||||
|
||||
// 更新订单列表中的对应订单
|
||||
const index = orders.value.findIndex(o => o.id === orderId);
|
||||
if (index !== -1) {
|
||||
orders.value[index] = order;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取订单详情失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取最近订单
|
||||
const fetchRecentOrders = async () => {
|
||||
try {
|
||||
const orders = await fetchRecentOrders();
|
||||
recentOrders.value = orders;
|
||||
const ordersData = await fetchRecentOrders();
|
||||
recentOrders.value = ordersData;
|
||||
} catch (error) {
|
||||
console.error('获取最近订单失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 取消订单
|
||||
const cancelOrder = async (orderId: string) => {
|
||||
try {
|
||||
await cancelOrder(orderId);
|
||||
const index = orders.value.findIndex(o => o.id === orderId);
|
||||
if (index !== -1) {
|
||||
orders.value[index].status = 'canceled';
|
||||
orders.value[index].statusText = '已取消';
|
||||
}
|
||||
if (currentOrder.value?.id === orderId) {
|
||||
currentOrder.value.status = 'canceled';
|
||||
currentOrder.value.statusText = '已取消';
|
||||
}
|
||||
uni.showToast({
|
||||
title: '订单已取消',
|
||||
icon: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '取消订单失败',
|
||||
icon: 'none'
|
||||
});
|
||||
console.error('取消订单失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 确认收货
|
||||
const acceptOrder = async (orderId: string) => {
|
||||
try {
|
||||
await acceptOrder(orderId);
|
||||
const index = orders.value.findIndex(o => o.id === orderId);
|
||||
if (index !== -1) {
|
||||
orders.value[index].status = 'completed';
|
||||
orders.value[index].statusText = '已完成';
|
||||
}
|
||||
if (currentOrder.value?.id === orderId) {
|
||||
currentOrder.value.status = 'completed';
|
||||
currentOrder.value.statusText = '已完成';
|
||||
}
|
||||
uni.showToast({
|
||||
title: '订单已完成',
|
||||
icon: 'success'
|
||||
});
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '确认收货失败',
|
||||
icon: 'none'
|
||||
});
|
||||
console.error('确认收货失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 创建订单
|
||||
const createOrder = async (form: IOrderCreateForm) => {
|
||||
try {
|
||||
const newOrder = await createOrder(form);
|
||||
orders.value.unshift(newOrder);
|
||||
return newOrder;
|
||||
} catch (error) {
|
||||
console.error('创建订单失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取运输详情
|
||||
const fetchTransportDetail = async (orderId: string): Promise<ITransportDetail> => {
|
||||
try {
|
||||
const detail = await fetchTransportDetail(orderId);
|
||||
if (currentOrder.value?.id === orderId) {
|
||||
currentOrder.value.transportInfo = detail;
|
||||
}
|
||||
return detail;
|
||||
} catch (error) {
|
||||
console.error('获取运输详情失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
pendingCount,
|
||||
inTransitCount,
|
||||
@@ -52,8 +176,16 @@ export const useOrderStore = defineStore('order', () => {
|
||||
totalAmount,
|
||||
totalWeight,
|
||||
averagePrice,
|
||||
orders,
|
||||
recentOrders,
|
||||
currentOrder,
|
||||
fetchOrderStats,
|
||||
fetchRecentOrders
|
||||
fetchOrders,
|
||||
fetchOrderDetail,
|
||||
fetchRecentOrders,
|
||||
createOrder,
|
||||
cancelOrder,
|
||||
acceptOrder,
|
||||
fetchTransportDetail
|
||||
};
|
||||
});
|
||||
41
mini_program/client-mp/src/stores/supplier.ts
Normal file
41
mini_program/client-mp/src/stores/supplier.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { ref } from 'vue';
|
||||
import type { ISupplier, ICattleBreed } from '@/types/supplier';
|
||||
import { fetchSuppliers, fetchCattleBreeds } from '@/api/supplier';
|
||||
|
||||
export const useSupplierStore = defineStore('supplier', () => {
|
||||
// 供应商列表
|
||||
const suppliers = ref<ISupplier[]>([]);
|
||||
|
||||
// 牛只品种列表
|
||||
const cattleBreeds = ref<ICattleBreed[]>([]);
|
||||
|
||||
// 获取供应商列表
|
||||
const fetchSuppliers = async () => {
|
||||
try {
|
||||
const data = await fetchSuppliers();
|
||||
suppliers.value = data;
|
||||
} catch (error) {
|
||||
console.error('获取供应商列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取牛只品种列表
|
||||
const fetchCattleBreeds = async () => {
|
||||
try {
|
||||
const data = await fetchCattleBreeds();
|
||||
cattleBreeds.value = data;
|
||||
} catch (error) {
|
||||
console.error('获取牛只品种列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
suppliers,
|
||||
cattleBreeds,
|
||||
fetchSuppliers,
|
||||
fetchCattleBreeds
|
||||
};
|
||||
});
|
||||
27
mini_program/client-mp/src/types/acceptance.ts
Normal file
27
mini_program/client-mp/src/types/acceptance.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// 验收状态
|
||||
export type AcceptanceStatus = 'pending' | 'passed' | 'failed';
|
||||
|
||||
// 验收基本信息
|
||||
export interface IAcceptance {
|
||||
id: string;
|
||||
orderId: string;
|
||||
status: AcceptanceStatus;
|
||||
acceptanceTime: string;
|
||||
result: string;
|
||||
acceptor?: string;
|
||||
}
|
||||
|
||||
// 验收详情
|
||||
export interface IAcceptanceDetail extends IAcceptance {
|
||||
images: string[];
|
||||
note?: string;
|
||||
cattleCount: number;
|
||||
qualifiedCount: number;
|
||||
unqualifiedReason?: string;
|
||||
weightDifference?: number;
|
||||
temperatureRecords?: {
|
||||
cattleId: string;
|
||||
temperature: number;
|
||||
status: 'normal' | 'abnormal';
|
||||
}[];
|
||||
}
|
||||
14
mini_program/client-mp/src/types/auth.ts
Normal file
14
mini_program/client-mp/src/types/auth.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// 登录表单
|
||||
export interface ILoginForm {
|
||||
username: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
// 注册表单
|
||||
export interface IRegisterForm {
|
||||
username: string;
|
||||
password: string;
|
||||
phone: string;
|
||||
captcha: string;
|
||||
role: 'client' | 'supplier' | 'driver' | 'staff';
|
||||
}
|
||||
@@ -7,20 +7,35 @@ export type OrderStatus =
|
||||
| 'completed'
|
||||
| 'canceled';
|
||||
|
||||
// 运输信息
|
||||
export interface ITransportInfo {
|
||||
driverName: string;
|
||||
driverPhone: string;
|
||||
licensePlate: string;
|
||||
estimatedArrival: string;
|
||||
currentLocation?: string;
|
||||
distanceRemaining?: string;
|
||||
}
|
||||
|
||||
// 订单基础信息
|
||||
export interface IOrder {
|
||||
id: string;
|
||||
orderNo: string;
|
||||
supplierId: string;
|
||||
supplierName: string;
|
||||
supplierContact?: string;
|
||||
supplierPhone?: string;
|
||||
cattleBreed: string;
|
||||
quantity: number;
|
||||
weight: number;
|
||||
price: number;
|
||||
totalAmount: number;
|
||||
status: OrderStatus;
|
||||
statusText: string;
|
||||
statusDesc?: string;
|
||||
createTime: string;
|
||||
updateTime: string;
|
||||
transportInfo?: ITransportInfo;
|
||||
}
|
||||
|
||||
// 订单统计信息
|
||||
|
||||
23
mini_program/client-mp/src/types/payment.ts
Normal file
23
mini_program/client-mp/src/types/payment.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// 支付状态
|
||||
export type PaymentStatus = 'pending' | 'paid' | 'failed';
|
||||
|
||||
// 支付方式
|
||||
export type PaymentMethod = 'wechat' | 'alipay' | 'bank';
|
||||
|
||||
// 支付基本信息
|
||||
export interface IPayment {
|
||||
id: string;
|
||||
orderId: string;
|
||||
amount: number;
|
||||
status: PaymentStatus;
|
||||
paymentMethod: PaymentMethod;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
// 支付详情
|
||||
export interface IPaymentDetail extends IPayment {
|
||||
paidTime?: string;
|
||||
transactionId?: string;
|
||||
paymentParams?: any;
|
||||
receiptUrl?: string;
|
||||
}
|
||||
20
mini_program/client-mp/src/types/supplier.ts
Normal file
20
mini_program/client-mp/src/types/supplier.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// 供应商信息
|
||||
export interface ISupplier {
|
||||
id: string;
|
||||
name: string;
|
||||
contact: string;
|
||||
phone: string;
|
||||
address: string;
|
||||
licenseNumber: string;
|
||||
rating?: number;
|
||||
}
|
||||
|
||||
// 牛只品种
|
||||
export interface ICattleBreed {
|
||||
id: string;
|
||||
name: string;
|
||||
price: number;
|
||||
description?: string;
|
||||
averageWeight?: number;
|
||||
origin?: string;
|
||||
}
|
||||
51
mini_program/client-mp/src/types/transport.ts
Normal file
51
mini_program/client-mp/src/types/transport.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
// 运输状态
|
||||
export type TransportStatus =
|
||||
| 'preparing' // 准备中
|
||||
| 'loading' // 装车中
|
||||
| 'in-transit' // 运输中
|
||||
| 'paused' // 暂停中
|
||||
| 'completed' // 已完成
|
||||
| 'abnormal'; // 异常状态
|
||||
|
||||
// 牛只运输状态
|
||||
export interface ICattleTransportStatus {
|
||||
id: string; // 牛只ID
|
||||
status: 'normal' | 'abnormal'; // 状态
|
||||
statusText: string; // 状态描述
|
||||
temperature?: number; // 体温
|
||||
heartRate?: number; // 心率
|
||||
}
|
||||
|
||||
// 运输详情
|
||||
export interface ITransportDetail {
|
||||
orderId: string; // 订单ID
|
||||
status: TransportStatus; // 运输状态
|
||||
statusText: string; // 状态描述
|
||||
currentLocation: string; // 当前位置
|
||||
latitude: number; // 纬度
|
||||
longitude: number; // 经度
|
||||
distanceTraveled: number; // 已行驶距离(公里)
|
||||
distance: number; // 总距离(公里)
|
||||
speed: number; // 当前速度(公里/小时)
|
||||
driverName: string; // 司机姓名
|
||||
driverPhone: string; // 司机电话
|
||||
cattleStatus: ICattleTransportStatus[]; // 牛只状态
|
||||
hasWarning: boolean; // 是否有异常预警
|
||||
warningMessage?: string; // 预警信息
|
||||
updatedAt: string; // 最后更新时间
|
||||
}
|
||||
|
||||
// 运输更新数据
|
||||
export interface ITransportUpdate {
|
||||
status?: TransportStatus;
|
||||
statusText?: string;
|
||||
currentLocation?: string;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
distanceTraveled?: number;
|
||||
speed?: number;
|
||||
cattleStatus?: ICattleTransportStatus[];
|
||||
hasWarning?: boolean;
|
||||
warningMessage?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/acceptance.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/acceptance.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"acceptance.js","sources":["api/acceptance.ts"],"sourcesContent":["import { request } from '@/utils/request';\nimport type { IAcceptance, IAcceptanceDetail } from '@/types/acceptance';\n\n// 获取验收列表\nexport const fetchAcceptanceList = async (): Promise<IAcceptance[]> => {\n try {\n const res = await request({\n url: '/acceptance/list',\n method: 'GET'\n });\n return res.data;\n } catch (error) {\n console.error('获取验收列表失败:', error);\n throw error;\n }\n};\n\n// 获取验收详情\nexport const fetchAcceptanceDetail = async (acceptanceId: string): Promise<IAcceptanceDetail> => {\n try {\n const res = await request({\n url: `/acceptance/${acceptanceId}/detail`,\n method: 'GET'\n });\n return res.data;\n } catch (error) {\n console.error('获取验收详情失败:', error);\n throw error;\n }\n};\n\n// 提交验收结果\nexport const submitAcceptance = async (data: {\n orderId: string;\n result: 'passed' | 'failed';\n images: string[];\n note?: string;\n}): Promise<IAcceptanceDetail> => {\n try {\n const res = await request({\n url: '/acceptance/submit',\n method: 'POST',\n data\n });\n return res.data;\n } catch (error) {\n console.error('提交验收结果失败:', error);\n throw error;\n }\n};"],"names":["request","uni"],"mappings":";;;AAIO,MAAM,sBAAsB,YAAoC;AACjE,MAAA;AACI,UAAA,MAAM,MAAMA,sBAAQ;AAAA,MACxB,KAAK;AAAA,MACL,QAAQ;AAAA,IAAA,CACT;AACD,WAAO,IAAI;AAAA,WACJ,OAAO;AACdC,kBAAA,MAAA,MAAA,SAAA,2BAAc,aAAa,KAAK;AAC1B,UAAA;AAAA,EACR;AACF;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/auth.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/auth.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.js","sources":["api/auth.ts"],"sourcesContent":["import { request } from '@/utils/request';\ninterface ILoginForm {\n username: string;\n password: string;\n}\n\ninterface IRegisterForm {\n username: string;\n password: string;\n phone: string;\n captcha: string;\n role: 'client' | 'supplier' | 'driver' | 'staff';\n}\n\n// 用户登录\nexport const login = async (data: ILoginForm) => {\n return request({\n url: '/auth/login',\n method: 'POST',\n data\n });\n};\n\n// 用户注册\nexport const register = async (data: IRegisterForm) => {\n return request({\n url: '/auth/register',\n method: 'POST',\n data\n });\n};\n\n// 获取验证码\nexport const getCaptcha = async (phone: string) => {\n return request({\n url: '/auth/captcha',\n method: 'GET',\n data: { phone }\n });\n};\n\n// 验证验证码\nexport const verifyCaptcha = async (phone: string, code: string) => {\n return request({\n url: '/auth/verify-captcha',\n method: 'POST',\n data: { phone, code }\n });\n};"],"names":["request"],"mappings":";;AAea,MAAA,QAAQ,OAAO,SAAqB;AAC/C,SAAOA,sBAAQ;AAAA,IACb,KAAK;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,EAAA,CACD;AACH;AAGa,MAAA,WAAW,OAAO,SAAwB;AACrD,SAAOA,sBAAQ;AAAA,IACb,KAAK;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,EAAA,CACD;AACH;AAGa,MAAA,aAAa,OAAO,UAAkB;AACjD,SAAOA,sBAAQ;AAAA,IACb,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,MAAM,EAAE,MAAM;AAAA,EAAA,CACf;AACH;;;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/payment.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/payment.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"payment.js","sources":["api/payment.ts"],"sourcesContent":["import { request } from '@/utils/request';\nimport type { IPayment, IPaymentDetail } from '@/types/payment';\n\n// 获取支付列表\nexport const fetchPaymentList = async (): Promise<IPayment[]> => {\n try {\n const res = await request({\n url: '/payment/list',\n method: 'GET'\n });\n return res.data;\n } catch (error) {\n console.error('获取支付列表失败:', error);\n throw error;\n }\n};\n\n// 获取支付详情\nexport const fetchPaymentDetail = async (paymentId: string): Promise<IPaymentDetail> => {\n try {\n const res = await request({\n url: `/payment/${paymentId}/detail`,\n method: 'GET'\n });\n return res.data;\n } catch (error) {\n console.error('获取支付详情失败:', error);\n throw error;\n }\n};\n\n// 发起支付\nexport const createPayment = async (orderId: string, amount: number, method: string): Promise<{\n paymentId: string;\n paymentParams: any;\n}> => {\n try {\n const res = await request({\n url: '/payment/create',\n method: 'POST',\n data: { orderId, amount, method }\n });\n return res.data;\n } catch (error) {\n console.error('创建支付失败:', error);\n throw error;\n }\n};\n\n// 查询支付状态\nexport const checkPaymentStatus = async (paymentId: string): Promise<{\n status: 'pending' | 'paid' | 'failed';\n paidTime?: string;\n}> => {\n try {\n const res = await request({\n url: `/payment/${paymentId}/status`,\n method: 'GET'\n });\n return res.data;\n } catch (error) {\n console.error('查询支付状态失败:', error);\n throw error;\n }\n};"],"names":["request","uni"],"mappings":";;;AAIO,MAAM,mBAAmB,YAAiC;AAC3D,MAAA;AACI,UAAA,MAAM,MAAMA,sBAAQ;AAAA,MACxB,KAAK;AAAA,MACL,QAAQ;AAAA,IAAA,CACT;AACD,WAAO,IAAI;AAAA,WACJ,OAAO;AACdC,kBAAA,MAAA,MAAA,SAAA,wBAAc,aAAa,KAAK;AAC1B,UAAA;AAAA,EACR;AACF;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/statistics.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/statistics.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"statistics.js","sources":["api/statistics.ts"],"sourcesContent":["import { request } from '@/utils/request';\n\n// 获取采购统计数据\nexport const getPurchaseStats = async (params: { \n startDate?: string;\n endDate?: string;\n}) => {\n return request({\n url: '/stats/purchase',\n method: 'GET',\n data: params\n });\n};\n\n// 获取运输统计数据\nexport const getTransportStats = async () => {\n return request({\n url: '/stats/transport',\n method: 'GET'\n });\n};\n\n// 获取财务统计数据\nexport const getFinancialStats = async () => {\n return request({\n url: '/stats/financial',\n method: 'GET'\n });\n};"],"names":["request"],"mappings":";;AAGa,MAAA,mBAAmB,OAAO,WAGjC;AACJ,SAAOA,sBAAQ;AAAA,IACb,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,MAAM;AAAA,EAAA,CACP;AACH;AAGO,MAAM,oBAAoB,YAAY;AAC3C,SAAOA,sBAAQ;AAAA,IACb,KAAK;AAAA,IACL,QAAQ;AAAA,EAAA,CACT;AACH;AAGO,MAAM,oBAAoB,YAAY;AAC3C,SAAOA,sBAAQ;AAAA,IACb,KAAK;AAAA,IACL,QAAQ;AAAA,EAAA,CACT;AACH;;;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/tracking.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/tracking.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"tracking.js","sources":["api/tracking.ts"],"sourcesContent":["import { request } from '@/utils/request';\n\n// 获取运输跟踪列表\nexport const fetchTrackingList = (params?: {\n status?: string;\n page?: number;\n pageSize?: number;\n}) => {\n return request({\n url: '/api/tracking/list',\n method: 'GET',\n params\n });\n};\n\n// 获取运输跟踪详情\nexport const fetchTrackingDetail = (id: string) => {\n return request({\n url: `/api/tracking/${id}`,\n method: 'GET'\n });\n};\n\n// 更新运输状态\nexport const updateTrackingStatus = (data: {\n id: string;\n status: string;\n location?: string;\n remark?: string;\n}) => {\n return request({\n url: '/api/tracking/update',\n method: 'POST',\n data\n });\n};\n\n// 获取运输历史记录\nexport const getTrackingHistory = (id: string) => {\n return request({\n url: `/api/tracking/${id}/history`,\n method: 'GET'\n });\n};\n\n// 订阅实时位置更新\nexport const subscribeTracking = (id: string) => {\n return request({\n url: `/api/tracking/${id}/subscribe`,\n method: 'GET'\n });\n};"],"names":["request"],"mappings":";;AAGa,MAAA,oBAAoB,CAAC,WAI5B;AACJ,SAAOA,sBAAQ;AAAA,IACb,KAAK;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,EAAA,CACD;AACH;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/user.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/api/user.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"user.js","sources":["api/user.ts"],"sourcesContent":["import { request } from '@/utils/request';\nimport type { IUser, IUserSettings } from '@/types/user';\n\n// 更新用户设置\nexport const updateUserSettings = async (settings: Partial<IUserSettings>) => {\n try {\n const res = await request({\n url: '/user/settings',\n method: 'POST',\n data: settings\n });\n return res.data;\n } catch (error) {\n console.error('更新用户设置失败:', error);\n throw error;\n }\n};\n\n// 获取用户详细信息(包含个人资料)\nexport const fetchUserProfile = async (): Promise<IUser & { profile: any }> => {\n try {\n const res = await request({\n url: '/user/profile',\n method: 'GET'\n });\n return res.data;\n } catch (error) {\n console.error('获取用户资料失败:', error);\n throw error;\n }\n};\n\n// 获取用户信息\nexport const fetchUserInfo = async (): Promise<IUser> => {\n try {\n const res = await request({\n url: '/user/info',\n method: 'GET'\n });\n return res.data;\n } catch (error) {\n console.error('获取用户信息失败:', error);\n throw error;\n }\n};"],"names":["request","uni"],"mappings":";;;AAIa,MAAA,qBAAqB,OAAO,aAAqC;AACxE,MAAA;AACI,UAAA,MAAM,MAAMA,sBAAQ;AAAA,MACxB,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,IAAA,CACP;AACD,WAAO,IAAI;AAAA,WACJ,OAAO;AACdC,kBAAA,MAAA,MAAA,SAAA,qBAAc,aAAa,KAAK;AAC1B,UAAA;AAAA,EACR;AACF;AAGO,MAAM,mBAAmB,YAA+C;AACzE,MAAA;AACI,UAAA,MAAM,MAAMD,sBAAQ;AAAA,MACxB,KAAK;AAAA,MACL,QAAQ;AAAA,IAAA,CACT;AACD,WAAO,IAAI;AAAA,WACJ,OAAO;AACdC,kBAAA,MAAA,MAAA,SAAA,qBAAc,aAAa,KAAK;AAC1B,UAAA;AAAA,EACR;AACF;;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/app.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"app.js","sources":["App.vue","main.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { onLaunch, onShow, onHide } from '@dcloudio/uni-app';\nimport { useUserStore } from '@/stores/user';\n\nconst userStore = useUserStore();\n\nonLaunch(() => {\n uni.__f__('log','at App.vue:8','App Launch');\n // 初始化时检查登录状态\n userStore.checkLoginStatus();\n});\n\nonShow(() => {\n uni.__f__('log','at App.vue:14','App Show');\n});\n\nonHide(() => {\n uni.__f__('log','at App.vue:18','App Hide');\n});\n</script>\n\n<template>\n <view>\n <!-- 这里是所有页面的容器 -->\n <slot />\n </view>\n</template>\n\n<style>\n/* 全局样式 */\npage {\n font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,\n Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei',\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n font-weight: 400;\n font-size: 14px;\n color: #333;\n background-color: #f8f8f8;\n}\n</style>","import { createSSRApp } from 'vue';\nimport App from './App.vue';\nimport { createPinia } from 'pinia';\nimport * as Pinia from 'pinia';\n\nexport function createApp() {\n const app = createSSRApp(App);\n const pinia = createPinia();\n \n // 配置Pinia\n pinia.use(({ store }) => {\n // 持久化存储\n const storageKey = `pinia_${store.$id}`;\n const savedState = uni.getStorageSync(storageKey);\n if (savedState) {\n store.$patch(JSON.parse(savedState));\n }\n \n store.$subscribe((mutation, state) => {\n uni.setStorageSync(storageKey, JSON.stringify(state));\n });\n });\n\n app.use(pinia);\n \n return {\n app,\n pinia\n };\n}"],"names":["useUserStore","onLaunch","uni","onShow","onHide","createSSRApp","App","createPinia"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAIA,UAAM,YAAYA,YAAAA;AAElBC,kBAAAA,SAAS,MAAM;AACTC,oBAAAA,MAAA,MAAM,OAAM,gBAAe,YAAY;AAE3C,gBAAU,iBAAiB;AAAA,IAAA,CAC5B;AAEDC,kBAAAA,OAAO,MAAM;AACPD,oBAAAA,MAAA,MAAM,OAAM,iBAAgB,UAAU;AAAA,IAAA,CAC3C;AAEDE,kBAAAA,OAAO,MAAM;AACPF,oBAAAA,MAAA,MAAM,OAAM,iBAAgB,UAAU;AAAA,IAAA,CAC3C;;;;;;ACbM,SAAS,YAAY;AACpB,QAAA,MAAMG,2BAAaC,SAAG;AAC5B,QAAM,QAAQC,cAAAA;AAGd,QAAM,IAAI,CAAC,EAAE,YAAY;AAEjB,UAAA,aAAa,SAAS,MAAM,GAAG;AAC/B,UAAA,aAAaL,cAAAA,MAAI,eAAe,UAAU;AAChD,QAAI,YAAY;AACd,YAAM,OAAO,KAAK,MAAM,UAAU,CAAC;AAAA,IACrC;AAEM,UAAA,WAAW,CAAC,UAAU,UAAU;AACpCA,oBAAA,MAAI,eAAe,YAAY,KAAK,UAAU,KAAK,CAAC;AAAA,IAAA,CACrD;AAAA,EAAA,CACF;AAED,MAAI,IAAI,KAAK;AAEN,SAAA;AAAA,IACL;AAAA,IACA;AAAA,EAAA;AAEJ;AACA,YAAY,IAAI,MAAM,MAAM;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/common/assets.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/common/assets.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"assets.js","sources":["../../../../../../../../static/images/empty-order.png"],"sourcesContent":["export default \"/static/images/empty-order.png\""],"names":[],"mappings":";AAAA,MAAe,aAAA;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"uni-icons.js","sources":["node_modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons.vue","/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/node_modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons.vue?type=component"],"sourcesContent":["<template>\r\n\t<!-- #ifdef APP-NVUE -->\r\n\t<text :style=\"styleObj\" class=\"uni-icons\" @click=\"_onClick\">{{unicode}}</text>\r\n\t<!-- #endif -->\r\n\t<!-- #ifndef APP-NVUE -->\r\n\t<text :style=\"styleObj\" class=\"uni-icons\" :class=\"['uniui-'+type,customPrefix,customPrefix?type:'']\" @click=\"_onClick\">\r\n\t\t<slot></slot>\r\n\t</text>\r\n\t<!-- #endif -->\r\n</template>\r\n\r\n<script>\r\n\timport { fontData } from './uniicons_file_vue.js';\r\n\r\n\tconst getVal = (val) => {\r\n\t\tconst reg = /^[0-9]*$/g\r\n\t\treturn (typeof val === 'number' || reg.test(val)) ? val + 'px' : val;\r\n\t}\r\n\r\n\t// #ifdef APP-NVUE\r\n\tvar domModule = weex.requireModule('dom');\r\n\timport iconUrl from './uniicons.ttf'\r\n\tdomModule.addRule('fontFace', {\r\n\t\t'fontFamily': \"uniicons\",\r\n\t\t'src': \"url('\" + iconUrl + \"')\"\r\n\t});\r\n\t// #endif\r\n\r\n\t/**\r\n\t * Icons 图标\r\n\t * @description 用于展示 icons 图标\r\n\t * @tutorial https://ext.dcloud.net.cn/plugin?id=28\r\n\t * @property {Number} size 图标大小\r\n\t * @property {String} type 图标图案,参考示例\r\n\t * @property {String} color 图标颜色\r\n\t * @property {String} customPrefix 自定义图标\r\n\t * @event {Function} click 点击 Icon 触发事件\r\n\t */\r\n\texport default {\r\n\t\tname: 'UniIcons',\r\n\t\temits: ['click'],\r\n\t\tprops: {\r\n\t\t\ttype: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t},\r\n\t\t\tcolor: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: '#333333'\r\n\t\t\t},\r\n\t\t\tsize: {\r\n\t\t\t\ttype: [Number, String],\r\n\t\t\t\tdefault: 16\r\n\t\t\t},\r\n\t\t\tcustomPrefix: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t},\r\n\t\t\tfontFamily: {\r\n\t\t\t\ttype: String,\r\n\t\t\t\tdefault: ''\r\n\t\t\t}\r\n\t\t},\r\n\t\tdata() {\r\n\t\t\treturn {\r\n\t\t\t\ticons: fontData\r\n\t\t\t}\r\n\t\t},\r\n\t\tcomputed: {\r\n\t\t\tunicode() {\r\n\t\t\t\tlet code = this.icons.find(v => v.font_class === this.type)\r\n\t\t\t\tif (code) {\r\n\t\t\t\t\treturn code.unicode\r\n\t\t\t\t}\r\n\t\t\t\treturn ''\r\n\t\t\t},\r\n\t\t\ticonSize() {\r\n\t\t\t\treturn getVal(this.size)\r\n\t\t\t},\r\n\t\t\tstyleObj() {\r\n\t\t\t\tif (this.fontFamily !== '') {\r\n\t\t\t\t\treturn `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`\r\n\t\t\t\t}\r\n\t\t\t\treturn `color: ${this.color}; font-size: ${this.iconSize};`\r\n\t\t\t}\r\n\t\t},\r\n\t\tmethods: {\r\n\t\t\t_onClick(e) {\r\n\t\t\t\tthis.$emit('click', e)\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n</script>\r\n\r\n<style lang=\"scss\">\r\n\t/* #ifndef APP-NVUE */\r\n\t@import './uniicons.css';\r\n\r\n\t@font-face {\r\n\t\tfont-family: uniicons;\r\n\t\tsrc: url('./uniicons.ttf');\r\n\t}\r\n\r\n\t/* #endif */\r\n\t.uni-icons {\r\n\t\tfont-family: uniicons;\r\n\t\ttext-decoration: none;\r\n\t\ttext-align: center;\r\n\t}\r\n</style>","import Component from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/node_modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons.vue'\nwx.createComponent(Component)"],"names":["fontData"],"mappings":";;AAcC,MAAM,SAAS,CAAC,QAAQ;AACvB,QAAM,MAAM;AACZ,SAAQ,OAAO,QAAQ,YAAY,IAAI,KAAK,GAAG,IAAK,MAAM,OAAO;AAClE;AAqBA,MAAK,YAAU;AAAA,EACd,MAAM;AAAA,EACN,OAAO,CAAC,OAAO;AAAA,EACf,OAAO;AAAA,IACN,MAAM;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,IACT;AAAA,IACD,OAAO;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,IACT;AAAA,IACD,MAAM;AAAA,MACL,MAAM,CAAC,QAAQ,MAAM;AAAA,MACrB,SAAS;AAAA,IACT;AAAA,IACD,cAAc;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA,IACT;AAAA,IACD,YAAY;AAAA,MACX,MAAM;AAAA,MACN,SAAS;AAAA,IACV;AAAA,EACA;AAAA,EACD,OAAO;AACN,WAAO;AAAA,MACN,OAAOA,cAAO;AAAA,IACf;AAAA,EACA;AAAA,EACD,UAAU;AAAA,IACT,UAAU;AACT,UAAI,OAAO,KAAK,MAAM,KAAK,OAAK,EAAE,eAAe,KAAK,IAAI;AAC1D,UAAI,MAAM;AACT,eAAO,KAAK;AAAA,MACb;AACA,aAAO;AAAA,IACP;AAAA,IACD,WAAW;AACV,aAAO,OAAO,KAAK,IAAI;AAAA,IACvB;AAAA,IACD,WAAW;AACV,UAAI,KAAK,eAAe,IAAI;AAC3B,eAAO,UAAU,KAAK,KAAK,gBAAgB,KAAK,QAAQ,kBAAkB,KAAK,UAAU;AAAA,MAC1F;AACA,aAAO,UAAU,KAAK,KAAK,gBAAgB,KAAK,QAAQ;AAAA,IACzD;AAAA,EACA;AAAA,EACD,SAAS;AAAA,IACR,SAAS,GAAG;AACX,WAAK,MAAM,SAAS,CAAC;AAAA,IACtB;AAAA,EACD;AACD;;;;;;;;;;;AC1FD,GAAG,gBAAgB,SAAS;","x_google_ignoreList":[0]}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"acceptance-detail.js","sources":["pages/acceptance/acceptance-detail.vue","pages/acceptance/acceptance-detail.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport { useOrderStore } from '@/stores/order';\nimport { fetchAcceptanceDetail } from '@/api/acceptance';\n\nconst orderStore = useOrderStore();\nconst acceptanceDetail = ref<any>(null);\nconst loading = ref(false);\nconst error = ref('');\n\n// 获取验收详情\nconst getAcceptanceDetail = async (acceptanceId: string) => {\n try {\n loading.value = true;\n acceptanceDetail.value = await fetchAcceptanceDetail(acceptanceId);\n } catch (err) {\n error.value = '获取验收详情失败';\n uni.__f__('error','at pages/acceptance/acceptance-detail.vue:18','获取验收详情失败:', err);\n } finally {\n loading.value = false;\n }\n};\n\nonMounted(() => {\n const acceptanceId = ''; // 从路由参数获取\n if (acceptanceId) {\n getAcceptanceDetail(acceptanceId);\n }\n});\n</script>\n\n<template>\n <view class=\"container\">\n <!-- 验收详情 -->\n <view v-if=\"acceptanceDetail\" class=\"card\">\n <view class=\"flex-between\">\n <text class=\"text-bold\">订单号: {{ acceptanceDetail.orderId }}</text>\n <text :class=\"acceptanceDetail.status === 'passed' ? 'text-primary' : 'text-danger'\">\n {{ acceptanceDetail.status === 'passed' ? '验收通过' : '验收未通过' }}\n </text>\n </view>\n <view class=\"divider\"></view>\n <text>验收时间: {{ acceptanceDetail.acceptanceTime }}</text>\n <view class=\"margin-top-sm\">\n <text>验收人: {{ acceptanceDetail.acceptor }}</text>\n </view>\n <view class=\"margin-top-sm\">\n <text>验收结果: {{ acceptanceDetail.result }}</text>\n </view>\n <view class=\"margin-top-sm\" v-if=\"acceptanceDetail.images\">\n <text>验收照片:</text>\n <!-- 图片展示 -->\n </view>\n </view>\n\n <!-- 加载状态 -->\n <view class=\"flex-center\" v-if=\"loading\">\n <text>加载中...</text>\n </view>\n \n <!-- 错误信息 -->\n <view class=\"flex-center\" v-if=\"error\">\n <text class=\"text-danger\">{{ error }}</text>\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n margin-bottom: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/acceptance/acceptance-detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["useOrderStore","ref","onMounted","MiniProgramPage"],"mappings":";;;;;;AAKmBA,+BAAc;AAC3B,UAAA,mBAAmBC,kBAAS,IAAI;AAChC,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAepBC,kBAAAA,UAAU,MAAM;AAAA,IAId,CACD;;;;;;;;;;;;;;;;;;;;;;AC3BD,GAAG,WAAWC,SAAe;"}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"acceptance-list.js","sources":["pages/acceptance/acceptance-list.vue","pages/acceptance/acceptance-list.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport { useOrderStore } from '@/stores/order';\nimport { fetchAcceptanceList } from '@/api/acceptance';\n\nconst orderStore = useOrderStore();\nconst acceptanceList = ref<any[]>([]);\nconst loading = ref(false);\nconst error = ref('');\n\n// 获取验收列表\nconst getAcceptanceList = async () => {\n try {\n loading.value = true;\n acceptanceList.value = await fetchAcceptanceList();\n } catch (err) {\n error.value = '获取验收列表失败';\n uni.__f__('error','at pages/acceptance/acceptance-list.vue:18','获取验收列表失败:', err);\n } finally {\n loading.value = false;\n }\n};\n\nonMounted(() => {\n getAcceptanceList();\n});\n</script>\n\n<template>\n <view class=\"container\">\n <!-- 验收列表 -->\n <view v-for=\"item in acceptanceList\" :key=\"item.id\" class=\"card\">\n <view class=\"flex-between\">\n <text class=\"text-bold\">订单号: {{ item.orderId }}</text>\n <text :class=\"item.status === 'passed' ? 'text-primary' : 'text-danger'\">\n {{ item.status === 'passed' ? '验收通过' : '验收未通过' }}\n </text>\n </view>\n <view class=\"divider\"></view>\n <text>验收时间: {{ item.acceptanceTime }}</text>\n <view class=\"margin-top-sm\">\n <text>验收结果: {{ item.result }}</text>\n </view>\n </view>\n\n <!-- 加载状态 -->\n <view class=\"flex-center\" v-if=\"loading\">\n <text>加载中...</text>\n </view>\n \n <!-- 错误信息 -->\n <view class=\"flex-center\" v-if=\"error\">\n <text class=\"text-danger\">{{ error }}</text>\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n margin-bottom: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/acceptance/acceptance-list.vue'\nwx.createPage(MiniProgramPage)"],"names":["useOrderStore","ref","fetchAcceptanceList","uni","onMounted","MiniProgramPage"],"mappings":";;;;;;;AAKmBA,+BAAc;AAC3B,UAAA,iBAAiBC,kBAAW,CAAA,CAAE;AAC9B,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAGpB,UAAM,oBAAoB,YAAY;AAChC,UAAA;AACF,gBAAQ,QAAQ;AACD,uBAAA,QAAQ,MAAMC,eAAAA;eACtB,KAAK;AACZ,cAAM,QAAQ;AACdC,sBAAA,MAAI,MAAM,SAAQ,8CAA6C,aAAa,GAAG;AAAA,MAAA,UAC/E;AACA,gBAAQ,QAAQ;AAAA,MAClB;AAAA,IAAA;AAGFC,kBAAAA,UAAU,MAAM;AACI;IAAA,CACnB;;;;;;;;;;;;;;;;;;;;;;ACxBD,GAAG,WAAWC,SAAe;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/pages/auth/login.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/pages/auth/login.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"login.js","sources":["pages/auth/login.vue","pages/auth/login.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { useUserStore } from '@/stores/user';\nimport { login } from '@/api/auth';\n\nconst userStore = useUserStore();\nconst username = ref('');\nconst password = ref('');\nconst loading = ref(false);\nconst error = ref('');\n\n// 登录\nconst handleLogin = async () => {\n try {\n loading.value = true;\n error.value = '';\n const user = await login(username.value, password.value);\n userStore.setUser(user);\n uni.showToast({\n title: '登录成功',\n icon: 'success'\n });\n uni.switchTab({\n url: '/pages/index/index'\n });\n } catch (err) {\n error.value = '用户名或密码错误';\n uni.__f__('error','at pages/auth/login.vue:28','登录失败:', err);\n } finally {\n loading.value = false;\n }\n};\n</script>\n\n<template>\n <view class=\"container\">\n <view class=\"card\">\n <text class=\"text-bold\">登录</text>\n <view class=\"divider\"></view>\n \n <view class=\"margin-top\">\n <text>用户名</text>\n <input v-model=\"username\" placeholder=\"请输入用户名\" />\n </view>\n \n <view class=\"margin-top\">\n <text>密码</text>\n <input v-model=\"password\" placeholder=\"请输入密码\" type=\"password\" />\n </view>\n \n <button \n class=\"margin-top\" \n type=\"primary\" \n :loading=\"loading\"\n @click=\"handleLogin\"\n >\n 登录\n </button>\n \n <view class=\"margin-top text-center\">\n <text>还没有账号?</text>\n <text class=\"text-primary\" @click=\"uni.navigateTo({ url: '/pages/auth/register' })\">立即注册</text>\n </view>\n </view>\n \n <view v-if=\"error\" class=\"text-danger text-center margin-top\">\n {{ error }}\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n\ninput {\n border: 1rpx solid #eee;\n border-radius: 8rpx;\n padding: 10rpx;\n margin-top: 10rpx;\n width: 100%;\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/auth/login.vue'\nwx.createPage(MiniProgramPage)"],"names":["useUserStore","ref","login","uni","MiniProgramPage"],"mappings":";;;;;;;AAKA,UAAM,YAAYA,YAAAA;AACZ,UAAA,WAAWC,kBAAI,EAAE;AACjB,UAAA,WAAWA,kBAAI,EAAE;AACjB,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAGpB,UAAM,cAAc,YAAY;AAC1B,UAAA;AACF,gBAAQ,QAAQ;AAChB,cAAM,QAAQ;AACd,cAAM,OAAO,MAAMC,eAAM,SAAS,OAAO,SAAS,KAAK;AACvD,kBAAU,QAAQ,IAAI;AACtBC,sBAAAA,MAAI,UAAU;AAAA,UACZ,OAAO;AAAA,UACP,MAAM;AAAA,QAAA,CACP;AACDA,sBAAAA,MAAI,UAAU;AAAA,UACZ,KAAK;AAAA,QAAA,CACN;AAAA,eACM,KAAK;AACZ,cAAM,QAAQ;AACdA,sBAAA,MAAI,MAAM,SAAQ,8BAA6B,SAAS,GAAG;AAAA,MAAA,UAC3D;AACA,gBAAQ,QAAQ;AAAA,MAClB;AAAA,IAAA;;;;;;;;;;;;;;;;;;;AC7BF,GAAG,WAAWC,SAAe;"}
|
||||
File diff suppressed because one or more lines are too long
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"payment-detail.js","sources":["pages/payment/payment-detail.vue","pages/payment/payment-detail.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport { useOrderStore } from '@/stores/order';\nimport { fetchPaymentDetail } from '@/api/payment';\n\nconst orderStore = useOrderStore();\nconst paymentDetail = ref<any>(null);\nconst loading = ref(false);\nconst error = ref('');\n\n// 获取支付详情\nconst getPaymentDetail = async (paymentId: string) => {\n try {\n loading.value = true;\n paymentDetail.value = await fetchPaymentDetail(paymentId);\n } catch (err) {\n error.value = '获取支付详情失败';\n uni.__f__('error','at pages/payment/payment-detail.vue:18','获取支付详情失败:', err);\n } finally {\n loading.value = false;\n }\n};\n\nonMounted(() => {\n const paymentId = ''; // 从路由参数获取\n if (paymentId) {\n getPaymentDetail(paymentId);\n }\n});\n</script>\n\n<template>\n <view class=\"container\">\n <!-- 支付详情 -->\n <view v-if=\"paymentDetail\" class=\"card\">\n <view class=\"flex-between\">\n <text class=\"text-bold\">订单号: {{ paymentDetail.orderId }}</text>\n <text :class=\"paymentDetail.status === 'paid' ? 'text-primary' : 'text-warning'\">\n {{ paymentDetail.status === 'paid' ? '已支付' : '待支付' }}\n </text>\n </view>\n <view class=\"divider\"></view>\n <text>金额: ¥{{ paymentDetail.amount }}</text>\n <view class=\"margin-top-sm\">\n <text>支付方式: {{ paymentDetail.paymentMethod }}</text>\n </view>\n <view class=\"margin-top-sm\" v-if=\"paymentDetail.status === 'paid'\">\n <text>支付时间: {{ paymentDetail.paidTime }}</text>\n </view>\n <view class=\"margin-top-sm\">\n <button type=\"primary\" v-if=\"paymentDetail.status === 'pending'\">立即支付</button>\n </view>\n </view>\n\n <!-- 加载状态 -->\n <view class=\"flex-center\" v-if=\"loading\">\n <text>加载中...</text>\n </view>\n \n <!-- 错误信息 -->\n <view class=\"flex-center\" v-if=\"error\">\n <text class=\"text-danger\">{{ error }}</text>\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n margin-bottom: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/payment/payment-detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["useOrderStore","ref","onMounted","MiniProgramPage"],"mappings":";;;;;;AAKmBA,+BAAc;AAC3B,UAAA,gBAAgBC,kBAAS,IAAI;AAC7B,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAepBC,kBAAAA,UAAU,MAAM;AAAA,IAId,CACD;;;;;;;;;;;;;;;;;;;;;;;;;AC3BD,GAAG,WAAWC,SAAe;"}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"payment-list.js","sources":["pages/payment/payment-list.vue","pages/payment/payment-list.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport { useOrderStore } from '@/stores/order';\nimport { fetchPaymentList } from '@/api/payment';\n\nconst orderStore = useOrderStore();\nconst paymentList = ref<any[]>([]);\nconst loading = ref(false);\nconst error = ref('');\n\n// 获取支付列表\nconst getPaymentList = async () => {\n try {\n loading.value = true;\n paymentList.value = await fetchPaymentList();\n } catch (err) {\n error.value = '获取支付列表失败';\n uni.__f__('error','at pages/payment/payment-list.vue:18','获取支付列表失败:', err);\n } finally {\n loading.value = false;\n }\n};\n\nonMounted(() => {\n getPaymentList();\n});\n</script>\n\n<template>\n <view class=\"container\">\n <!-- 支付列表 -->\n <view v-for=\"item in paymentList\" :key=\"item.id\" class=\"card\">\n <view class=\"flex-between\">\n <text class=\"text-bold\">订单号: {{ item.orderId }}</text>\n <text :class=\"item.status === 'paid' ? 'text-primary' : 'text-warning'\">\n {{ item.status === 'paid' ? '已支付' : '待支付' }}\n </text>\n </view>\n <view class=\"divider\"></view>\n <text>金额: ¥{{ item.amount }}</text>\n <view class=\"margin-top-sm\">\n <text>支付方式: {{ item.paymentMethod }}</text>\n </view>\n </view>\n\n <!-- 加载状态 -->\n <view class=\"flex-center\" v-if=\"loading\">\n <text>加载中...</text>\n </view>\n \n <!-- 错误信息 -->\n <view class=\"flex-center\" v-if=\"error\">\n <text class=\"text-danger\">{{ error }}</text>\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n margin-bottom: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/payment/payment-list.vue'\nwx.createPage(MiniProgramPage)"],"names":["useOrderStore","ref","fetchPaymentList","uni","onMounted","MiniProgramPage"],"mappings":";;;;;;;AAKmBA,+BAAc;AAC3B,UAAA,cAAcC,kBAAW,CAAA,CAAE;AAC3B,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAGpB,UAAM,iBAAiB,YAAY;AAC7B,UAAA;AACF,gBAAQ,QAAQ;AACJ,oBAAA,QAAQ,MAAMC,YAAAA;eACnB,KAAK;AACZ,cAAM,QAAQ;AACdC,sBAAA,MAAI,MAAM,SAAQ,wCAAuC,aAAa,GAAG;AAAA,MAAA,UACzE;AACA,gBAAQ,QAAQ;AAAA,MAClB;AAAA,IAAA;AAGFC,kBAAAA,UAAU,MAAM;AACC;IAAA,CAChB;;;;;;;;;;;;;;;;;;;;;;ACxBD,GAAG,WAAWC,SAAe;"}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"statistics.js","sources":["pages/statistics/statistics.vue","pages/statistics/statistics.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport { getPurchaseStats, getTransportStats, getFinancialStats } from '@/api/statistics';\n\nconst statistics = ref<any>(null);\nconst loading = ref(false);\nconst error = ref('');\n\n// 获取统计数据\nconst getStatistics = async () => {\n try {\n loading.value = true;\n const [purchase, transport, financial] = await Promise.all([\n getPurchaseStats(),\n getTransportStats(),\n getFinancialStats()\n ]);\n statistics.value = {\n ...purchase,\n ...transport,\n ...financial\n };\n } catch (err) {\n error.value = '获取统计数据失败';\n uni.__f__('error','at pages/statistics/statistics.vue:25','获取统计数据失败:', err);\n } finally {\n loading.value = false;\n }\n};\n\nonMounted(() => {\n getStatistics();\n});\n</script>\n\n<template>\n <view class=\"container\">\n <!-- 统计数据 -->\n <view v-if=\"statistics\" class=\"card\">\n <text class=\"text-bold\">采购统计</text>\n <view class=\"divider\"></view>\n <view class=\"flex-between margin-top-sm\">\n <text>总采购量: {{ statistics.totalPurchase }}头</text>\n <text>总金额: ¥{{ statistics.totalAmount }}</text>\n </view>\n <view class=\"flex-between margin-top-sm\">\n <text>平均价格: ¥{{ statistics.averagePrice }}/头</text>\n <text>平均重量: {{ statistics.averageWeight }}kg</text>\n </view>\n </view>\n\n <!-- 图表区域 -->\n <view class=\"card margin-top\">\n <text class=\"text-bold\">采购趋势</text>\n <view class=\"divider\"></view>\n <!-- 这里将集成图表组件 -->\n <view class=\"chart-placeholder\">\n <text>采购趋势图表</text>\n </view>\n </view>\n\n <!-- 加载状态 -->\n <view class=\"flex-center\" v-if=\"loading\">\n <text>加载中...</text>\n </view>\n \n <!-- 错误信息 -->\n <view class=\"flex-center\" v-if=\"error\">\n <text class=\"text-danger\">{{ error }}</text>\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n margin-bottom: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n\n.chart-placeholder {\n height: 300rpx;\n background-color: #f5f5f5;\n border-radius: 8rpx;\n display: flex;\n justify-content: center;\n align-items: center;\n margin-top: 20rpx;\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/statistics/statistics.vue'\nwx.createPage(MiniProgramPage)"],"names":["ref","getPurchaseStats","getTransportStats","getFinancialStats","uni","onMounted","MiniProgramPage"],"mappings":";;;;;;AAIM,UAAA,aAAaA,kBAAS,IAAI;AAC1B,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAGpB,UAAM,gBAAgB,YAAY;AAC5B,UAAA;AACF,gBAAQ,QAAQ;AAChB,cAAM,CAAC,UAAU,WAAW,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,UACzDC,gCAAiB;AAAA,UACjBC,iCAAkB;AAAA,UAClBC,iCAAkB;AAAA,QAAA,CACnB;AACD,mBAAW,QAAQ;AAAA,UACjB,GAAG;AAAA,UACH,GAAG;AAAA,UACH,GAAG;AAAA,QAAA;AAAA,eAEE,KAAK;AACZ,cAAM,QAAQ;AACdC,sBAAA,MAAI,MAAM,SAAQ,yCAAwC,aAAa,GAAG;AAAA,MAAA,UAC1E;AACA,gBAAQ,QAAQ;AAAA,MAClB;AAAA,IAAA;AAGFC,kBAAAA,UAAU,MAAM;AACA;IAAA,CACf;;;;;;;;;;;;;;;;;;;AC/BD,GAAG,WAAWC,SAAe;"}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"tracking-detail.js","sources":["pages/tracking/tracking-detail.vue","pages/tracking/tracking-detail.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport { useOrderStore } from '@/stores/order';\nimport { \n fetchTrackingDetail,\n updateTrackingStatus,\n subscribeTracking\n} from '@/api/tracking';\n\nconst orderStore = useOrderStore();\nconst trackingDetail = ref<any>(null);\nconst loading = ref(false);\nconst error = ref('');\n\n// 获取运输详情\nconst getTrackingDetail = async (trackingId: string) => {\n try {\n loading.value = true;\n trackingDetail.value = await fetchTrackingDetail(trackingId);\n } catch (err) {\n error.value = '获取运输详情失败';\n uni.__f__('error','at pages/tracking/tracking-detail.vue:22','获取运输详情失败:', err);\n } finally {\n loading.value = false;\n }\n};\n\nonMounted(() => {\n const trackingId = ''; // 从路由参数获取\n if (trackingId) {\n getTrackingDetail(trackingId);\n }\n});\n</script>\n\n<template>\n <view class=\"container\">\n <!-- 运输详情 -->\n <view v-if=\"trackingDetail\" class=\"card\">\n <view class=\"flex-between\">\n <text class=\"text-bold\">订单号: {{ trackingDetail.orderId }}</text>\n <text :class=\"trackingDetail.status === 'completed' ? 'text-primary' : 'text-warning'\">\n {{ trackingDetail.status === 'completed' ? '已完成' : '运输中' }}\n </text>\n </view>\n <view class=\"divider\"></view>\n \n <view class=\"margin-top-sm\">\n <text>司机: {{ trackingDetail.driverName }}</text>\n </view>\n \n <view class=\"margin-top-sm\">\n <text>联系电话: {{ trackingDetail.driverPhone }}</text>\n </view>\n \n <view class=\"margin-top-sm\">\n <text>当前位置: {{ trackingDetail.currentLocation }}</text>\n </view>\n \n <view class=\"margin-top-sm\">\n <text>预计到达: {{ trackingDetail.estimatedArrival }}</text>\n </view>\n \n <view class=\"margin-top-sm\">\n <text>已行驶距离: {{ trackingDetail.distanceTraveled }}公里</text>\n </view>\n \n <view class=\"margin-top-sm\">\n <text>剩余距离: {{ trackingDetail.remainingDistance }}公里</text>\n </view>\n \n <!-- 地图容器 -->\n <view class=\"map-container margin-top\">\n <text>地图显示区域</text>\n </view>\n </view>\n\n <!-- 加载状态 -->\n <view class=\"flex-center\" v-if=\"loading\">\n <text>加载中...</text>\n </view>\n \n <!-- 错误信息 -->\n <view class=\"flex-center\" v-if=\"error\">\n <text class=\"text-danger\">{{ error }}</text>\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n\n.map-container {\n height: 300rpx;\n background-color: #f5f5f5;\n border-radius: 8rpx;\n display: flex;\n justify-content: center;\n align-items: center;\n margin-top: 20rpx;\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/tracking/tracking-detail.vue'\nwx.createPage(MiniProgramPage)"],"names":["useOrderStore","ref","onMounted","MiniProgramPage"],"mappings":";;;;;;AASmBA,+BAAc;AAC3B,UAAA,iBAAiBC,kBAAS,IAAI;AAC9B,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAepBC,kBAAAA,UAAU,MAAM;AAAA,IAId,CACD;;;;;;;;;;;;;;;;;;;;;;;;AC/BD,GAAG,WAAWC,SAAe;"}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"tracking-list.js","sources":["pages/tracking/tracking-list.vue","pages/tracking/tracking-list.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport { useOrderStore } from '@/stores/order';\nimport { fetchTrackingList } from '@/api/tracking';\n\nconst orderStore = useOrderStore();\nconst trackingList = ref<any[]>([]);\nconst loading = ref(false);\nconst error = ref('');\n\n// 获取运输跟踪列表\nconst getTrackingList = async () => {\n try {\n loading.value = true;\n trackingList.value = await fetchTrackingList();\n } catch (err) {\n error.value = '获取运输跟踪列表失败';\n uni.__f__('error','at pages/tracking/tracking-list.vue:18','获取运输跟踪列表失败:', err);\n } finally {\n loading.value = false;\n }\n};\n\nonMounted(() => {\n getTrackingList();\n});\n</script>\n\n<template>\n <view class=\"container\">\n <!-- 运输跟踪列表 -->\n <view v-for=\"item in trackingList\" :key=\"item.id\" class=\"card\">\n <view class=\"flex-between\">\n <text class=\"text-bold\">订单号: {{ item.orderId }}</text>\n <text :class=\"item.status === 'completed' ? 'text-primary' : 'text-warning'\">\n {{ item.status === 'completed' ? '已完成' : '运输中' }}\n </text>\n </view>\n <view class=\"divider\"></view>\n <text>司机: {{ item.driverName }}</text>\n <view class=\"margin-top-sm\">\n <text>当前位置: {{ item.currentLocation }}</text>\n </view>\n <view class=\"margin-top-sm\">\n <text>预计到达: {{ item.estimatedArrival }}</text>\n </view>\n </view>\n\n <!-- 加载状态 -->\n <view class=\"flex-center\" v-if=\"loading\">\n <text>加载中...</text>\n </view>\n \n <!-- 错误信息 -->\n <view class=\"flex-center\" v-if=\"error\">\n <text class=\"text-danger\">{{ error }}</text>\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n margin-bottom: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/tracking/tracking-list.vue'\nwx.createPage(MiniProgramPage)"],"names":["useOrderStore","ref","fetchTrackingList","uni","onMounted","MiniProgramPage"],"mappings":";;;;;;;AAKmBA,+BAAc;AAC3B,UAAA,eAAeC,kBAAW,CAAA,CAAE;AAC5B,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAGpB,UAAM,kBAAkB,YAAY;AAC9B,UAAA;AACF,gBAAQ,QAAQ;AACH,qBAAA,QAAQ,MAAMC,aAAAA;eACpB,KAAK;AACZ,cAAM,QAAQ;AACdC,sBAAA,MAAI,MAAM,SAAQ,0CAAyC,eAAe,GAAG;AAAA,MAAA,UAC7E;AACA,gBAAQ,QAAQ;AAAA,MAClB;AAAA,IAAA;AAGFC,kBAAAA,UAAU,MAAM;AACE;IAAA,CACjB;;;;;;;;;;;;;;;;;;;;;;;ACxBD,GAAG,WAAWC,SAAe;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/pages/user/profile.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/pages/user/profile.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"profile.js","sources":["pages/user/profile.vue","pages/user/profile.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, onMounted } from 'vue';\nimport { useUserStore } from '@/stores/user';\nimport { fetchUserProfile } from '@/api/user';\n\nconst userStore = useUserStore();\nconst profile = ref<any>(null);\nconst loading = ref(false);\nconst error = ref('');\n\n// 获取用户信息\nconst getUserProfile = async () => {\n try {\n loading.value = true;\n profile.value = await fetchUserProfile();\n } catch (err) {\n error.value = '获取用户信息失败';\n uni.__f__('error','at pages/user/profile.vue:18','获取用户信息失败:', err);\n } finally {\n loading.value = false;\n }\n};\n\n// 退出登录\nconst handleLogout = () => {\n userStore.clearUser();\n uni.redirectTo({\n url: '/pages/auth/login'\n });\n};\n\nonMounted(() => {\n getUserProfile();\n});\n</script>\n\n<template>\n <view class=\"container\">\n <!-- 用户信息 -->\n <view class=\"card\" v-if=\"profile\">\n <view class=\"flex-center\">\n <image \n :src=\"profile.avatar || '/static/default-avatar.png'\" \n mode=\"aspectFill\"\n class=\"avatar\"\n />\n </view>\n \n <view class=\"divider\"></view>\n \n <view class=\"margin-top\">\n <text class=\"text-bold\">用户名: {{ profile.username }}</text>\n </view>\n \n <view class=\"margin-top\">\n <text>手机号: {{ profile.phone }}</text>\n </view>\n \n <view class=\"margin-top\">\n <text>注册时间: {{ profile.createdAt }}</text>\n </view>\n \n <button \n class=\"margin-top\" \n type=\"warn\" \n @click=\"handleLogout\"\n >\n 退出登录\n </button>\n </view>\n \n <!-- 加载状态 -->\n <view class=\"flex-center\" v-if=\"loading\">\n <text>加载中...</text>\n </view>\n \n <!-- 错误信息 -->\n <view class=\"flex-center\" v-if=\"error\">\n <text class=\"text-danger\">{{ error }}</text>\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n\n.avatar {\n width: 150rpx;\n height: 150rpx;\n border-radius: 50%;\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/user/profile.vue'\nwx.createPage(MiniProgramPage)"],"names":["useUserStore","ref","fetchUserProfile","uni","onMounted","MiniProgramPage"],"mappings":";;;;;;;AAKA,UAAM,YAAYA,YAAAA;AACZ,UAAA,UAAUC,kBAAS,IAAI;AACvB,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAGpB,UAAM,iBAAiB,YAAY;AAC7B,UAAA;AACF,gBAAQ,QAAQ;AACR,gBAAA,QAAQ,MAAMC,SAAAA;eACf,KAAK;AACZ,cAAM,QAAQ;AACdC,sBAAA,MAAI,MAAM,SAAQ,gCAA+B,aAAa,GAAG;AAAA,MAAA,UACjE;AACA,gBAAQ,QAAQ;AAAA,MAClB;AAAA,IAAA;AAIF,UAAM,eAAe,MAAM;AACzB,gBAAU,UAAU;AACpBA,oBAAAA,MAAI,WAAW;AAAA,QACb,KAAK;AAAA,MAAA,CACN;AAAA,IAAA;AAGHC,kBAAAA,UAAU,MAAM;AACC;IAAA,CAChB;;;;;;;;;;;;;;;;;;;;AChCD,GAAG,WAAWC,SAAe;"}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"settings.js","sources":["pages/user/settings.vue","pages/user/settings.vue?type=page"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport { useUserStore } from '@/stores/user';\nimport { updateUserSettings } from '@/api/user';\n\nconst userStore = useUserStore();\nconst settings = ref({\n notification: true,\n darkMode: false,\n language: 'zh-CN'\n});\nconst loading = ref(false);\nconst error = ref('');\n\n// 保存设置\nconst saveSettings = async () => {\n try {\n loading.value = true;\n await updateUserSettings(settings.value);\n uni.showToast({\n title: '设置已保存',\n icon: 'success'\n });\n } catch (err) {\n error.value = '保存设置失败';\n uni.__f__('error','at pages/user/settings.vue:26','保存设置失败:', err);\n } finally {\n loading.value = false;\n }\n};\n</script>\n\n<template>\n <view class=\"container\">\n <view class=\"card\">\n <text class=\"text-bold\">系统设置</text>\n <view class=\"divider\"></view>\n \n <view class=\"setting-item\">\n <text>消息通知</text>\n <switch :checked=\"settings.notification\" @change=\"(e: any) => settings.notification = e.detail.value\" />\n </view>\n \n <view class=\"setting-item\">\n <text>深色模式</text>\n <switch :checked=\"settings.darkMode\" @change=\"(e: any) => settings.darkMode = e.detail.value\" />\n </view>\n \n <view class=\"setting-item\">\n <text>语言设置</text>\n <picker mode=\"selector\" :range=\"['简体中文', 'English']\">\n <text>{{ settings.language === 'zh-CN' ? '简体中文' : 'English' }}</text>\n </picker>\n </view>\n \n <button \n class=\"margin-top\" \n type=\"primary\" \n :loading=\"loading\"\n @click=\"saveSettings\"\n >\n 保存设置\n </button>\n </view>\n \n <view v-if=\"error\" class=\"text-danger text-center margin-top\">\n {{ error }}\n </view>\n </view>\n</template>\n\n<style lang=\"scss\">\n.container {\n padding: 20rpx;\n}\n\n.card {\n background-color: #fff;\n border-radius: 8rpx;\n padding: 20rpx;\n box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);\n}\n\n.setting-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 20rpx 0;\n border-bottom: 1rpx solid #eee;\n}\n</style>","import MiniProgramPage from '/Users/ainongkeji/code/vue/niumall/mini_program/client-mp/src/pages/user/settings.vue'\nwx.createPage(MiniProgramPage)"],"names":["useUserStore","ref","updateUserSettings","uni","MiniProgramPage"],"mappings":";;;;;;;AAKkBA,6BAAa;AAC/B,UAAM,WAAWC,cAAAA,IAAI;AAAA,MACnB,cAAc;AAAA,MACd,UAAU;AAAA,MACV,UAAU;AAAA,IAAA,CACX;AACK,UAAA,UAAUA,kBAAI,KAAK;AACnB,UAAA,QAAQA,kBAAI,EAAE;AAGpB,UAAM,eAAe,YAAY;AAC3B,UAAA;AACF,gBAAQ,QAAQ;AACV,cAAAC,SAAA,mBAAmB,SAAS,KAAK;AACvCC,sBAAAA,MAAI,UAAU;AAAA,UACZ,OAAO;AAAA,UACP,MAAM;AAAA,QAAA,CACP;AAAA,eACM,KAAK;AACZ,cAAM,QAAQ;AACdA,sBAAA,MAAI,MAAM,SAAQ,iCAAgC,WAAW,GAAG;AAAA,MAAA,UAChE;AACA,gBAAQ,QAAQ;AAAA,MAClB;AAAA,IAAA;;;;;;;;;;;;;;;;;;AC3BF,GAAG,WAAWC,SAAe;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/stores/order.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/stores/order.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/stores/supplier.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/stores/supplier.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"supplier.js","sources":["stores/supplier.ts"],"sourcesContent":["import { defineStore } from 'pinia';\nimport { ref } from 'vue';\nimport type { ISupplier, ICattleBreed } from '@/types/supplier';\nimport { fetchSuppliers, fetchCattleBreeds } from '@/api/supplier';\n\nexport const useSupplierStore = defineStore('supplier', () => {\n // 供应商列表\n const suppliers = ref<ISupplier[]>([]);\n \n // 牛只品种列表\n const cattleBreeds = ref<ICattleBreed[]>([]);\n \n // 获取供应商列表\n const fetchSuppliers = async () => {\n try {\n const data = await fetchSuppliers();\n suppliers.value = data;\n } catch (error) {\n console.error('获取供应商列表失败:', error);\n throw error;\n }\n };\n \n // 获取牛只品种列表\n const fetchCattleBreeds = async () => {\n try {\n const data = await fetchCattleBreeds();\n cattleBreeds.value = data;\n } catch (error) {\n console.error('获取牛只品种列表失败:', error);\n throw error;\n }\n };\n \n return {\n suppliers,\n cattleBreeds,\n fetchSuppliers,\n fetchCattleBreeds\n };\n});"],"names":["defineStore","ref","fetchSuppliers","uni","fetchCattleBreeds"],"mappings":";;AAKa,MAAA,mBAAmBA,cAAAA,YAAY,YAAY,MAAM;AAEtD,QAAA,YAAYC,kBAAiB,CAAA,CAAE;AAG/B,QAAA,eAAeA,kBAAoB,CAAA,CAAE;AAG3C,QAAMC,kBAAiB,YAAY;AAC7B,QAAA;AACI,YAAA,OAAO,MAAMA;AACnB,gBAAU,QAAQ;AAAA,aACX,OAAO;AACdC,oBAAA,MAAc,MAAA,SAAA,4BAAA,cAAc,KAAK;AAC3B,YAAA;AAAA,IACR;AAAA,EAAA;AAIF,QAAMC,qBAAoB,YAAY;AAChC,QAAA;AACI,YAAA,OAAO,MAAMA;AACnB,mBAAa,QAAQ;AAAA,aACd,OAAO;AACdD,oBAAA,MAAc,MAAA,SAAA,4BAAA,eAAe,KAAK;AAC5B,YAAA;AAAA,IACR;AAAA,EAAA;AAGK,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IACA,gBAAAD;AAAAA,IACA,mBAAAE;AAAAA,EAAA;AAEJ,CAAC;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/stores/user.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/stores/user.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"user.js","sources":["stores/user.ts"],"sourcesContent":["import { defineStore } from 'pinia';\nimport { ref } from 'vue';\nimport type { IUser } from '@/types/user';\nimport { fetchUserInfo } from '@/api/user';\n\nexport const useUserStore = defineStore('user', () => {\n // 用户信息\n const userInfo = ref<IUser>({\n id: '',\n name: '加载中...',\n avatar: '/static/images/default-avatar.png',\n lastLogin: '',\n phone: '',\n company: '',\n role: 'client'\n });\n \n // 获取用户信息\n const fetchUserInfo = async () => {\n try {\n const info = await fetchUserInfo();\n userInfo.value = info;\n } catch (error) {\n console.error('获取用户信息失败:', error);\n throw error;\n }\n };\n \n return {\n userInfo,\n fetchUserInfo\n };\n});"],"names":["defineStore","ref","fetchUserInfo","uni"],"mappings":";;AAKa,MAAA,eAAeA,cAAAA,YAAY,QAAQ,MAAM;AAEpD,QAAM,WAAWC,cAAAA,IAAW;AAAA,IAC1B,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,EAAA,CACP;AAGD,QAAMC,iBAAgB,YAAY;AAC5B,QAAA;AACI,YAAA,OAAO,MAAMA;AACnB,eAAS,QAAQ;AAAA,aACV,OAAO;AACdC,oBAAA,6CAAc,aAAa,KAAK;AAC1B,YAAA;AAAA,IACR;AAAA,EAAA;AAGK,SAAA;AAAA,IACL;AAAA,IACA,eAAAD;AAAAA,EAAA;AAEJ,CAAC;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/utils/feedback.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/utils/feedback.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"feedback.js","sources":["utils/feedback.ts"],"sourcesContent":["// 显示成功提示\nexport const showSuccess = (title: string, duration = 1500) => {\n uni.showToast({\n title,\n icon: 'success',\n duration\n });\n};\n\n// 显示错误提示\nexport const showError = (title: string, duration = 1500) => {\n uni.showToast({\n title,\n icon: 'none',\n duration\n });\n};\n\n// 显示加载中\nexport const showLoading = (title = '加载中...') => {\n uni.showLoading({ title });\n};\n\n// 隐藏加载中\nexport const hideLoading = () => {\n uni.hideLoading();\n};\n\n// 显示确认对话框\nexport const showConfirm = (options: {\n title?: string;\n content: string;\n confirmText?: string;\n cancelText?: string;\n}) => {\n return new Promise<boolean>((resolve) => {\n uni.showModal({\n ...options,\n success: (res) => {\n resolve(res.confirm);\n }\n });\n });\n};"],"names":["uni"],"mappings":";;AACO,MAAM,cAAc,CAAC,OAAe,WAAW,SAAS;AAC7DA,gBAAAA,MAAI,UAAU;AAAA,IACZ;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EAAA,CACD;AACH;AAGO,MAAM,YAAY,CAAC,OAAe,WAAW,SAAS;AAC3DA,gBAAAA,MAAI,UAAU;AAAA,IACZ;AAAA,IACA,MAAM;AAAA,IACN;AAAA,EAAA,CACD;AACH;;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/utils/request.js.map
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/.sourcemap/mp-weixin/utils/request.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"request.js","sources":["utils/request.ts"],"sourcesContent":["import type { RequestOptions } from '@/types/request';\n\n// 环境配置\nconst config = {\n development: {\n baseURL: 'http://localhost:3001/api',\n wsURL: 'ws://localhost:3001'\n },\n production: {\n baseURL: 'https://api.niumall.com/api',\n wsURL: 'wss://api.niumall.com'\n }\n};\n\n// 当前环境\nconst env = process.env.NODE_ENV === 'production' ? 'production' : 'development';\nconst { baseURL, wsURL } = config[env];\n\n// 请求封装\nexport const request = (options: RequestOptions) => {\n return new Promise((resolve, reject) => {\n uni.request({\n url: baseURL + options.url,\n method: options.method || 'GET',\n data: options.data,\n header: {\n 'Authorization': `Bearer ${getToken()}`,\n 'Content-Type': 'application/json',\n ...options.header\n },\n success: (res) => {\n if (res.statusCode >= 200 && res.statusCode < 300) {\n resolve(res.data);\n } else {\n handleError(res);\n reject(res);\n }\n },\n fail: (err) => {\n handleError(err);\n reject(err);\n }\n });\n });\n};\n\n// WebSocket连接\nexport const connectWebSocket = () => {\n return uni.connectSocket({\n url: wsURL,\n success: () => {\n console.log('WebSocket连接成功');\n },\n fail: (err) => {\n console.error('WebSocket连接失败:', err);\n }\n });\n};\n\n// 获取token\nconst getToken = (): string => {\n try {\n const token = uni.getStorageSync('token');\n return token || '';\n } catch (e) {\n return '';\n }\n};\n\n// 错误处理\nconst handleError = (error: any) => {\n console.error('请求错误:', error);\n \n // 未授权\n if (error.statusCode === 401) {\n uni.redirectTo({\n url: '/pages/auth/login'\n });\n }\n \n // 其他错误\n uni.showToast({\n title: error.data?.message || '请求失败',\n icon: 'none'\n });\n};"],"names":["uni"],"mappings":";;AAGA,MAAM,SAAS;AAAA,EACb,aAAa;AAAA,IACX,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AACF;AAGA,MAAM,MAA6D;AACnE,MAAM,EAAE,SAAS,MAAM,IAAI,OAAO,GAAG;AAGxB,MAAA,UAAU,CAAC,YAA4B;AAClD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtCA,kBAAAA,MAAI,QAAQ;AAAA,MACV,KAAK,UAAU,QAAQ;AAAA,MACvB,QAAQ,QAAQ,UAAU;AAAA,MAC1B,MAAM,QAAQ;AAAA,MACd,QAAQ;AAAA,QACN,iBAAiB,UAAU,SAAA,CAAU;AAAA,QACrC,gBAAgB;AAAA,QAChB,GAAG,QAAQ;AAAA,MACb;AAAA,MACA,SAAS,CAAC,QAAQ;AAChB,YAAI,IAAI,cAAc,OAAO,IAAI,aAAa,KAAK;AACjD,kBAAQ,IAAI,IAAI;AAAA,QAAA,OACX;AACL,sBAAY,GAAG;AACf,iBAAO,GAAG;AAAA,QACZ;AAAA,MACF;AAAA,MACA,MAAM,CAAC,QAAQ;AACb,oBAAY,GAAG;AACf,eAAO,GAAG;AAAA,MACZ;AAAA,IAAA,CACD;AAAA,EAAA,CACF;AACH;AAgBA,MAAM,WAAW,MAAc;AACzB,MAAA;AACI,UAAA,QAAQA,cAAAA,MAAI,eAAe,OAAO;AACxC,WAAO,SAAS;AAAA,WACT,GAAG;AACH,WAAA;AAAA,EACT;AACF;AAGA,MAAM,cAAc,CAAC,UAAe;;AAClCA,gBAAA,MAAc,MAAA,SAAA,0BAAA,SAAS,KAAK;AAGxB,MAAA,MAAM,eAAe,KAAK;AAC5BA,kBAAAA,MAAI,WAAW;AAAA,MACb,KAAK;AAAA,IAAA,CACN;AAAA,EACH;AAGAA,gBAAAA,MAAI,UAAU;AAAA,IACZ,SAAO,WAAM,SAAN,mBAAY,YAAW;AAAA,IAC9B,MAAM;AAAA,EAAA,CACP;AACH;;"}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/App.wxml
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/App.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view><slot/></view>
|
||||
17
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/acceptance.js
vendored
Normal file
17
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/acceptance.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../common/vendor.js");
|
||||
const utils_request = require("../utils/request.js");
|
||||
const fetchAcceptanceList = async () => {
|
||||
try {
|
||||
const res = await utils_request.request({
|
||||
url: "/acceptance/list",
|
||||
method: "GET"
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
common_vendor.index.__f__("error", "at api/acceptance.ts:13", "获取验收列表失败:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
exports.fetchAcceptanceList = fetchAcceptanceList;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/api/acceptance.js.map
|
||||
27
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/auth.js
vendored
Normal file
27
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/auth.js
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
const utils_request = require("../utils/request.js");
|
||||
const login = async (data) => {
|
||||
return utils_request.request({
|
||||
url: "/auth/login",
|
||||
method: "POST",
|
||||
data
|
||||
});
|
||||
};
|
||||
const register = async (data) => {
|
||||
return utils_request.request({
|
||||
url: "/auth/register",
|
||||
method: "POST",
|
||||
data
|
||||
});
|
||||
};
|
||||
const getCaptcha = async (phone) => {
|
||||
return utils_request.request({
|
||||
url: "/auth/captcha",
|
||||
method: "GET",
|
||||
data: { phone }
|
||||
});
|
||||
};
|
||||
exports.getCaptcha = getCaptcha;
|
||||
exports.login = login;
|
||||
exports.register = register;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/api/auth.js.map
|
||||
17
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/payment.js
vendored
Normal file
17
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/payment.js
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../common/vendor.js");
|
||||
const utils_request = require("../utils/request.js");
|
||||
const fetchPaymentList = async () => {
|
||||
try {
|
||||
const res = await utils_request.request({
|
||||
url: "/payment/list",
|
||||
method: "GET"
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
common_vendor.index.__f__("error", "at api/payment.ts:13", "获取支付列表失败:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
exports.fetchPaymentList = fetchPaymentList;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/api/payment.js.map
|
||||
25
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/statistics.js
vendored
Normal file
25
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/statistics.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
const utils_request = require("../utils/request.js");
|
||||
const getPurchaseStats = async (params) => {
|
||||
return utils_request.request({
|
||||
url: "/stats/purchase",
|
||||
method: "GET",
|
||||
data: params
|
||||
});
|
||||
};
|
||||
const getTransportStats = async () => {
|
||||
return utils_request.request({
|
||||
url: "/stats/transport",
|
||||
method: "GET"
|
||||
});
|
||||
};
|
||||
const getFinancialStats = async () => {
|
||||
return utils_request.request({
|
||||
url: "/stats/financial",
|
||||
method: "GET"
|
||||
});
|
||||
};
|
||||
exports.getFinancialStats = getFinancialStats;
|
||||
exports.getPurchaseStats = getPurchaseStats;
|
||||
exports.getTransportStats = getTransportStats;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/api/statistics.js.map
|
||||
11
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/tracking.js
vendored
Normal file
11
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/tracking.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
const utils_request = require("../utils/request.js");
|
||||
const fetchTrackingList = (params) => {
|
||||
return utils_request.request({
|
||||
url: "/api/tracking/list",
|
||||
method: "GET",
|
||||
params
|
||||
});
|
||||
};
|
||||
exports.fetchTrackingList = fetchTrackingList;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/api/tracking.js.map
|
||||
31
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/user.js
vendored
Normal file
31
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/api/user.js
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../common/vendor.js");
|
||||
const utils_request = require("../utils/request.js");
|
||||
const updateUserSettings = async (settings) => {
|
||||
try {
|
||||
const res = await utils_request.request({
|
||||
url: "/user/settings",
|
||||
method: "POST",
|
||||
data: settings
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
common_vendor.index.__f__("error", "at api/user.ts:14", "更新用户设置失败:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
const fetchUserProfile = async () => {
|
||||
try {
|
||||
const res = await utils_request.request({
|
||||
url: "/user/profile",
|
||||
method: "GET"
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
common_vendor.index.__f__("error", "at api/user.ts:28", "获取用户资料失败:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
exports.fetchUserProfile = fetchUserProfile;
|
||||
exports.updateUserSettings = updateUserSettings;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/api/user.js.map
|
||||
62
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/app.js
vendored
Normal file
62
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/app.js
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const common_vendor = require("./common/vendor.js");
|
||||
const stores_user = require("./stores/user.js");
|
||||
if (!Math) {
|
||||
"./pages/index/index.js";
|
||||
"./pages/order/order-list.js";
|
||||
"./pages/order/order-detail.js";
|
||||
"./pages/order/order-create.js";
|
||||
"./pages/tracking/tracking-list.js";
|
||||
"./pages/tracking/tracking-detail.js";
|
||||
"./pages/acceptance/acceptance-list.js";
|
||||
"./pages/acceptance/acceptance-detail.js";
|
||||
"./pages/payment/payment-list.js";
|
||||
"./pages/payment/payment-detail.js";
|
||||
"./pages/statistics/statistics.js";
|
||||
"./pages/auth/login.js";
|
||||
"./pages/auth/register.js";
|
||||
"./pages/user/profile.js";
|
||||
"./pages/user/settings.js";
|
||||
}
|
||||
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
|
||||
__name: "App",
|
||||
setup(__props) {
|
||||
const userStore = stores_user.useUserStore();
|
||||
common_vendor.onLaunch(() => {
|
||||
common_vendor.index.__f__("log", "at App.vue:8", "App Launch");
|
||||
userStore.checkLoginStatus();
|
||||
});
|
||||
common_vendor.onShow(() => {
|
||||
common_vendor.index.__f__("log", "at App.vue:14", "App Show");
|
||||
});
|
||||
common_vendor.onHide(() => {
|
||||
common_vendor.index.__f__("log", "at App.vue:18", "App Hide");
|
||||
});
|
||||
return (_ctx, _cache) => {
|
||||
return {};
|
||||
};
|
||||
}
|
||||
});
|
||||
function createApp() {
|
||||
const app = common_vendor.createSSRApp(_sfc_main);
|
||||
const pinia = common_vendor.createPinia();
|
||||
pinia.use(({ store }) => {
|
||||
const storageKey = `pinia_${store.$id}`;
|
||||
const savedState = common_vendor.index.getStorageSync(storageKey);
|
||||
if (savedState) {
|
||||
store.$patch(JSON.parse(savedState));
|
||||
}
|
||||
store.$subscribe((mutation, state) => {
|
||||
common_vendor.index.setStorageSync(storageKey, JSON.stringify(state));
|
||||
});
|
||||
});
|
||||
app.use(pinia);
|
||||
return {
|
||||
app,
|
||||
pinia
|
||||
};
|
||||
}
|
||||
createApp().app.mount("#app");
|
||||
exports.createApp = createApp;
|
||||
//# sourceMappingURL=../.sourcemap/mp-weixin/app.js.map
|
||||
67
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/app.json
vendored
Normal file
67
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/app.json
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"pages": [
|
||||
"pages/index/index",
|
||||
"pages/order/order-list",
|
||||
"pages/order/order-detail",
|
||||
"pages/order/order-create",
|
||||
"pages/tracking/tracking-list",
|
||||
"pages/tracking/tracking-detail",
|
||||
"pages/acceptance/acceptance-list",
|
||||
"pages/acceptance/acceptance-detail",
|
||||
"pages/payment/payment-list",
|
||||
"pages/payment/payment-detail",
|
||||
"pages/statistics/statistics",
|
||||
"pages/auth/login",
|
||||
"pages/auth/register",
|
||||
"pages/user/profile",
|
||||
"pages/user/settings"
|
||||
],
|
||||
"window": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "活牛采购",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
},
|
||||
"tabBar": {
|
||||
"color": "#7A7E83",
|
||||
"selectedColor": "#3cc51f",
|
||||
"borderStyle": "black",
|
||||
"backgroundColor": "#ffffff",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/index/index",
|
||||
"iconPath": "static/images/tabbar/home.png",
|
||||
"selectedIconPath": "static/images/tabbar/home-active.png",
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/order/order-list",
|
||||
"iconPath": "static/images/tabbar/order.png",
|
||||
"selectedIconPath": "static/images/tabbar/order-active.png",
|
||||
"text": "订单"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/tracking/tracking-list",
|
||||
"iconPath": "static/images/tabbar/tracking.png",
|
||||
"selectedIconPath": "static/images/tabbar/tracking-active.png",
|
||||
"text": "跟踪"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/user/profile",
|
||||
"iconPath": "static/images/tabbar/user.png",
|
||||
"selectedIconPath": "static/images/tabbar/user-active.png",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
},
|
||||
"permission": {
|
||||
"scope.userLocation": {
|
||||
"desc": "您的位置信息将用于运输跟踪服务"
|
||||
}
|
||||
},
|
||||
"requiredPrivateInfos": [
|
||||
"getLocation",
|
||||
"chooseLocation"
|
||||
],
|
||||
"usingComponents": {}
|
||||
}
|
||||
14
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/app.wxss
vendored
Normal file
14
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/app.wxss
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
/* 全局样式 */
|
||||
page {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica,
|
||||
Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
page{--status-bar-height:25px;--top-window-height:0px;--window-top:0px;--window-bottom:0px;--window-left:0px;--window-right:0px;--window-magin:0px}[data-c-h="true"]{display: none !important;}
|
||||
4
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/common/assets.js
vendored
Normal file
4
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/common/assets.js
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
const _imports_0 = "/static/images/empty-order.png";
|
||||
exports._imports_0 = _imports_0;
|
||||
//# sourceMappingURL=../../.sourcemap/mp-weixin/common/assets.js.map
|
||||
9359
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/common/vendor.js
vendored
Normal file
9359
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/common/vendor.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../../../../common/vendor.js");
|
||||
const getVal = (val) => {
|
||||
const reg = /^[0-9]*$/g;
|
||||
return typeof val === "number" || reg.test(val) ? val + "px" : val;
|
||||
};
|
||||
const _sfc_main = {
|
||||
name: "UniIcons",
|
||||
emits: ["click"],
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: "#333333"
|
||||
},
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: 16
|
||||
},
|
||||
customPrefix: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
fontFamily: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
icons: common_vendor.fontData
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
unicode() {
|
||||
let code = this.icons.find((v) => v.font_class === this.type);
|
||||
if (code) {
|
||||
return code.unicode;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
iconSize() {
|
||||
return getVal(this.size);
|
||||
},
|
||||
styleObj() {
|
||||
if (this.fontFamily !== "") {
|
||||
return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`;
|
||||
}
|
||||
return `color: ${this.color}; font-size: ${this.iconSize};`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
_onClick(e) {
|
||||
this.$emit("click", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return {
|
||||
a: common_vendor.s($options.styleObj),
|
||||
b: common_vendor.n("uniui-" + $props.type),
|
||||
c: common_vendor.n($props.customPrefix),
|
||||
d: common_vendor.n($props.customPrefix ? $props.type : ""),
|
||||
e: common_vendor.o((...args) => $options._onClick && $options._onClick(...args))
|
||||
};
|
||||
}
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render]]);
|
||||
wx.createComponent(Component);
|
||||
//# sourceMappingURL=../../../../../../.sourcemap/mp-weixin/node-modules/@dcloudio/uni-ui/lib/uni-icons/uni-icons.js.map
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<text style="{{a}}" class="{{['uni-icons', b, c, d]}}" bindtap="{{e}}"><slot></slot></text>
|
||||
File diff suppressed because one or more lines are too long
35
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/acceptance/acceptance-detail.js
vendored
Normal file
35
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/acceptance/acceptance-detail.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const stores_order = require("../../stores/order.js");
|
||||
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
|
||||
__name: "acceptance-detail",
|
||||
setup(__props) {
|
||||
stores_order.useOrderStore();
|
||||
const acceptanceDetail = common_vendor.ref(null);
|
||||
const loading = common_vendor.ref(false);
|
||||
const error = common_vendor.ref("");
|
||||
common_vendor.onMounted(() => {
|
||||
});
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: acceptanceDetail.value
|
||||
}, acceptanceDetail.value ? common_vendor.e({
|
||||
b: common_vendor.t(acceptanceDetail.value.orderId),
|
||||
c: common_vendor.t(acceptanceDetail.value.status === "passed" ? "验收通过" : "验收未通过"),
|
||||
d: common_vendor.n(acceptanceDetail.value.status === "passed" ? "text-primary" : "text-danger"),
|
||||
e: common_vendor.t(acceptanceDetail.value.acceptanceTime),
|
||||
f: common_vendor.t(acceptanceDetail.value.acceptor),
|
||||
g: common_vendor.t(acceptanceDetail.value.result),
|
||||
h: acceptanceDetail.value.images
|
||||
}, acceptanceDetail.value.images ? {} : {}) : {}, {
|
||||
i: loading.value
|
||||
}, loading.value ? {} : {}, {
|
||||
j: error.value
|
||||
}, error.value ? {
|
||||
k: common_vendor.t(error.value)
|
||||
} : {});
|
||||
};
|
||||
}
|
||||
});
|
||||
wx.createPage(_sfc_main);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/acceptance/acceptance-detail.js.map
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "验收详情",
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<view class="container"><view wx:if="{{a}}" class="card"><view class="flex-between"><text class="text-bold">订单号: {{b}}</text><text class="{{d}}">{{c}}</text></view><view class="divider"></view><text>验收时间: {{e}}</text><view class="margin-top-sm"><text>验收人: {{f}}</text></view><view class="margin-top-sm"><text>验收结果: {{g}}</text></view><view wx:if="{{h}}" class="margin-top-sm"><text>验收照片:</text></view></view><view wx:if="{{i}}" class="flex-center"><text>加载中...</text></view><view wx:if="{{j}}" class="flex-center"><text class="text-danger">{{k}}</text></view></view>
|
||||
10
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/acceptance/acceptance-detail.wxss
vendored
Normal file
10
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/acceptance/acceptance-detail.wxss
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
48
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/acceptance/acceptance-list.js
vendored
Normal file
48
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/acceptance/acceptance-list.js
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const stores_order = require("../../stores/order.js");
|
||||
const api_acceptance = require("../../api/acceptance.js");
|
||||
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
|
||||
__name: "acceptance-list",
|
||||
setup(__props) {
|
||||
stores_order.useOrderStore();
|
||||
const acceptanceList = common_vendor.ref([]);
|
||||
const loading = common_vendor.ref(false);
|
||||
const error = common_vendor.ref("");
|
||||
const getAcceptanceList = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
acceptanceList.value = await api_acceptance.fetchAcceptanceList();
|
||||
} catch (err) {
|
||||
error.value = "获取验收列表失败";
|
||||
common_vendor.index.__f__("error", "at pages/acceptance/acceptance-list.vue:18", "获取验收列表失败:", err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
common_vendor.onMounted(() => {
|
||||
getAcceptanceList();
|
||||
});
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: common_vendor.f(acceptanceList.value, (item, k0, i0) => {
|
||||
return {
|
||||
a: common_vendor.t(item.orderId),
|
||||
b: common_vendor.t(item.status === "passed" ? "验收通过" : "验收未通过"),
|
||||
c: common_vendor.n(item.status === "passed" ? "text-primary" : "text-danger"),
|
||||
d: common_vendor.t(item.acceptanceTime),
|
||||
e: common_vendor.t(item.result),
|
||||
f: item.id
|
||||
};
|
||||
}),
|
||||
b: loading.value
|
||||
}, loading.value ? {} : {}, {
|
||||
c: error.value
|
||||
}, error.value ? {
|
||||
d: common_vendor.t(error.value)
|
||||
} : {});
|
||||
};
|
||||
}
|
||||
});
|
||||
wx.createPage(_sfc_main);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/acceptance/acceptance-list.js.map
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "验收管理",
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<view class="container"><view wx:for="{{a}}" wx:for-item="item" wx:key="f" class="card"><view class="flex-between"><text class="text-bold">订单号: {{item.a}}</text><text class="{{item.c}}">{{item.b}}</text></view><view class="divider"></view><text>验收时间: {{item.d}}</text><view class="margin-top-sm"><text>验收结果: {{item.e}}</text></view></view><view wx:if="{{b}}" class="flex-center"><text>加载中...</text></view><view wx:if="{{c}}" class="flex-center"><text class="text-danger">{{d}}</text></view></view>
|
||||
10
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/acceptance/acceptance-list.wxss
vendored
Normal file
10
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/acceptance/acceptance-list.wxss
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
52
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/login.js
vendored
Normal file
52
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/login.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const stores_user = require("../../stores/user.js");
|
||||
const api_auth = require("../../api/auth.js");
|
||||
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
|
||||
__name: "login",
|
||||
setup(__props) {
|
||||
const userStore = stores_user.useUserStore();
|
||||
const username = common_vendor.ref("");
|
||||
const password = common_vendor.ref("");
|
||||
const loading = common_vendor.ref(false);
|
||||
const error = common_vendor.ref("");
|
||||
const handleLogin = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = "";
|
||||
const user = await api_auth.login(username.value, password.value);
|
||||
userStore.setUser(user);
|
||||
common_vendor.index.showToast({
|
||||
title: "登录成功",
|
||||
icon: "success"
|
||||
});
|
||||
common_vendor.index.switchTab({
|
||||
url: "/pages/index/index"
|
||||
});
|
||||
} catch (err) {
|
||||
error.value = "用户名或密码错误";
|
||||
common_vendor.index.__f__("error", "at pages/auth/login.vue:28", "登录失败:", err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: username.value,
|
||||
b: common_vendor.o(($event) => username.value = $event.detail.value),
|
||||
c: password.value,
|
||||
d: common_vendor.o(($event) => password.value = $event.detail.value),
|
||||
e: loading.value,
|
||||
f: common_vendor.o(handleLogin),
|
||||
g: common_vendor.o(($event) => common_vendor.index.navigateTo({
|
||||
url: "/pages/auth/register"
|
||||
})),
|
||||
h: error.value
|
||||
}, error.value ? {
|
||||
i: common_vendor.t(error.value)
|
||||
} : {});
|
||||
};
|
||||
}
|
||||
});
|
||||
wx.createPage(_sfc_main);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/auth/login.js.map
|
||||
4
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/login.json
vendored
Normal file
4
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/login.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "登录",
|
||||
"usingComponents": {}
|
||||
}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/login.wxml
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/login.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view class="container"><view class="card"><text class="text-bold">登录</text><view class="divider"></view><view class="margin-top"><text>用户名</text><input placeholder="请输入用户名" value="{{a}}" bindinput="{{b}}"/></view><view class="margin-top"><text>密码</text><input placeholder="请输入密码" type="password" value="{{c}}" bindinput="{{d}}"/></view><button class="margin-top" type="primary" loading="{{e}}" bindtap="{{f}}"> 登录 </button><view class="margin-top text-center"><text>还没有账号?</text><text class="text-primary" bindtap="{{g}}">立即注册</text></view></view><view wx:if="{{h}}" class="text-danger text-center margin-top">{{i}}</view></view>
|
||||
16
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/login.wxss
vendored
Normal file
16
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/login.wxss
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
input {
|
||||
border: 1rpx solid #eee;
|
||||
border-radius: 8rpx;
|
||||
padding: 10rpx;
|
||||
margin-top: 10rpx;
|
||||
width: 100%;
|
||||
}
|
||||
94
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/register.js
vendored
Normal file
94
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/register.js
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const stores_user = require("../../stores/user.js");
|
||||
const api_auth = require("../../api/auth.js");
|
||||
const utils_feedback = require("../../utils/feedback.js");
|
||||
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
|
||||
__name: "register",
|
||||
setup(__props) {
|
||||
const userStore = stores_user.useUserStore();
|
||||
const form = common_vendor.ref({
|
||||
username: "",
|
||||
password: "",
|
||||
confirmPassword: "",
|
||||
phone: "",
|
||||
captcha: "",
|
||||
role: "client"
|
||||
});
|
||||
const captchaSent = common_vendor.ref(false);
|
||||
const countdown = common_vendor.ref(0);
|
||||
const loading = common_vendor.ref(false);
|
||||
const error = common_vendor.ref("");
|
||||
const sendCaptcha = async () => {
|
||||
if (!form.value.phone) {
|
||||
utils_feedback.showError("请输入手机号");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await api_auth.getCaptcha(form.value.phone);
|
||||
captchaSent.value = true;
|
||||
countdown.value = 60;
|
||||
const timer = setInterval(() => {
|
||||
countdown.value--;
|
||||
if (countdown.value <= 0) {
|
||||
clearInterval(timer);
|
||||
captchaSent.value = false;
|
||||
}
|
||||
}, 1e3);
|
||||
utils_feedback.showSuccess("验证码已发送");
|
||||
} catch (error2) {
|
||||
utils_feedback.showError("发送验证码失败");
|
||||
common_vendor.index.__f__("error", "at pages/auth/register.vue:41", "发送验证码失败:", error2);
|
||||
}
|
||||
};
|
||||
const submitRegister = async () => {
|
||||
if (form.value.password !== form.value.confirmPassword) {
|
||||
utils_feedback.showError("两次输入的密码不一致");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
loading.value = true;
|
||||
error.value = "";
|
||||
const user = await api_auth.register(form.value);
|
||||
userStore.setUser(user);
|
||||
utils_feedback.showSuccess("注册成功");
|
||||
setTimeout(() => {
|
||||
common_vendor.index.navigateBack();
|
||||
}, 1500);
|
||||
} catch (err) {
|
||||
error.value = "注册失败,请稍后再试";
|
||||
utils_feedback.showError("注册失败");
|
||||
common_vendor.index.__f__("error", "at pages/auth/register.vue:63", "注册失败:", err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
return (_ctx, _cache) => {
|
||||
return common_vendor.e({
|
||||
a: form.value.username,
|
||||
b: common_vendor.o(($event) => form.value.username = $event.detail.value),
|
||||
c: form.value.password,
|
||||
d: common_vendor.o(($event) => form.value.password = $event.detail.value),
|
||||
e: form.value.confirmPassword,
|
||||
f: common_vendor.o(($event) => form.value.confirmPassword = $event.detail.value),
|
||||
g: form.value.phone,
|
||||
h: common_vendor.o(($event) => form.value.phone = $event.detail.value),
|
||||
i: form.value.captcha,
|
||||
j: common_vendor.o(($event) => form.value.captcha = $event.detail.value),
|
||||
k: common_vendor.t(captchaSent.value ? `${countdown.value}秒后重试` : "获取验证码"),
|
||||
l: captchaSent.value,
|
||||
m: common_vendor.o(sendCaptcha),
|
||||
n: loading.value,
|
||||
o: common_vendor.o(submitRegister),
|
||||
p: common_vendor.o(($event) => common_vendor.index.navigateTo({
|
||||
url: "/pages/auth/login"
|
||||
})),
|
||||
q: error.value
|
||||
}, error.value ? {
|
||||
r: common_vendor.t(error.value)
|
||||
} : {});
|
||||
};
|
||||
}
|
||||
});
|
||||
wx.createPage(_sfc_main);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/auth/register.js.map
|
||||
4
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/register.json
vendored
Normal file
4
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/register.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"navigationBarTitleText": "注册",
|
||||
"usingComponents": {}
|
||||
}
|
||||
1
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/register.wxml
vendored
Normal file
1
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/register.wxml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<view class="container"><view class="card"><text class="text-bold">注册</text><view class="divider"></view><view class="form-item"><text class="label">用户名</text><input placeholder="请输入用户名" value="{{a}}" bindinput="{{b}}"/></view><view class="form-item"><text class="label">密码</text><input placeholder="请输入密码" type="password" value="{{c}}" bindinput="{{d}}"/></view><view class="form-item"><text class="label">确认密码</text><input placeholder="请再次输入密码" type="password" value="{{e}}" bindinput="{{f}}"/></view><view class="form-item"><text class="label">手机号</text><input placeholder="请输入手机号" type="number" value="{{g}}" bindinput="{{h}}"/></view><view class="form-item"><text class="label">验证码</text><view class="captcha-input"><input placeholder="请输入验证码" value="{{i}}" bindinput="{{j}}"/><button size="mini" disabled="{{l}}" bindtap="{{m}}">{{k}}</button></view></view><button type="primary" loading="{{n}}" bindtap="{{o}}"> 注册 </button><view class="login-link"><text>已有账号?</text><text class="text-primary" bindtap="{{p}}">立即登录</text></view></view><view wx:if="{{q}}" class="error-message">{{r}}</view></view>
|
||||
41
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/register.wxss
vendored
Normal file
41
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/auth/register.wxss
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.form-item {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.form-item .label {
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.form-item input {
|
||||
border: 1rpx solid #eee;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.captcha-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.captcha-input input {
|
||||
flex: 1;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.login-link {
|
||||
margin-top: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.error-message {
|
||||
margin-top: 20rpx;
|
||||
color: #ff3b30;
|
||||
text-align: center;
|
||||
}
|
||||
107
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/index/index.js
vendored
Normal file
107
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/index/index.js
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const stores_order = require("../../stores/order.js");
|
||||
const stores_user = require("../../stores/user.js");
|
||||
const _sfc_main = /* @__PURE__ */ common_vendor.defineComponent({
|
||||
__name: "index",
|
||||
setup(__props) {
|
||||
const orderStore = stores_order.useOrderStore();
|
||||
const userStore = stores_user.useUserStore();
|
||||
const homeData = common_vendor.ref({
|
||||
pendingOrders: 0,
|
||||
inTransitOrders: 0,
|
||||
pendingAcceptance: 0,
|
||||
pendingPayment: 0,
|
||||
recentOrders: [],
|
||||
statistics: {
|
||||
totalAmount: 0,
|
||||
totalWeight: 0,
|
||||
averagePrice: 0
|
||||
}
|
||||
});
|
||||
const loading = common_vendor.ref(false);
|
||||
const loadData = async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
await Promise.all([
|
||||
orderStore.fetchOrderStats(),
|
||||
orderStore.fetchRecentOrders(),
|
||||
userStore.fetchUserInfo()
|
||||
]);
|
||||
homeData.value = {
|
||||
pendingOrders: orderStore.pendingCount,
|
||||
inTransitOrders: orderStore.inTransitCount,
|
||||
pendingAcceptance: orderStore.pendingAcceptanceCount,
|
||||
pendingPayment: orderStore.pendingPaymentCount,
|
||||
recentOrders: orderStore.recentOrders.slice(0, 5),
|
||||
statistics: {
|
||||
totalAmount: orderStore.totalAmount,
|
||||
totalWeight: orderStore.totalWeight,
|
||||
averagePrice: orderStore.averagePrice
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
common_vendor.index.showToast({
|
||||
title: "加载数据失败",
|
||||
icon: "none"
|
||||
});
|
||||
common_vendor.index.__f__("error", "at pages/index/index.vue:53", "加载首页数据失败:", error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
common_vendor.onMounted(() => {
|
||||
loadData();
|
||||
});
|
||||
const onRefresh = () => {
|
||||
loadData();
|
||||
};
|
||||
const navigateToOrderList = (type) => {
|
||||
common_vendor.index.navigateTo({
|
||||
url: `/pages/order/order-list?type=${type}`
|
||||
});
|
||||
};
|
||||
const navigateToOrderDetail = (id) => {
|
||||
common_vendor.index.navigateTo({
|
||||
url: `/pages/order/order-detail?id=${id}`
|
||||
});
|
||||
};
|
||||
return (_ctx, _cache) => {
|
||||
return {
|
||||
a: common_vendor.t(common_vendor.unref(userStore).userInfo.name),
|
||||
b: common_vendor.t(common_vendor.unref(userStore).userInfo.lastLogin),
|
||||
c: common_vendor.unref(userStore).userInfo.avatar,
|
||||
d: common_vendor.o(($event) => navigateToOrderList("all")),
|
||||
e: common_vendor.t(homeData.value.pendingOrders),
|
||||
f: common_vendor.o(($event) => navigateToOrderList("pending")),
|
||||
g: common_vendor.t(homeData.value.inTransitOrders),
|
||||
h: common_vendor.o(($event) => navigateToOrderList("in_transit")),
|
||||
i: common_vendor.t(homeData.value.pendingAcceptance),
|
||||
j: common_vendor.o(($event) => navigateToOrderList("pending_acceptance")),
|
||||
k: common_vendor.t(homeData.value.pendingPayment),
|
||||
l: common_vendor.o(($event) => navigateToOrderList("pending_payment")),
|
||||
m: common_vendor.t(homeData.value.statistics.totalAmount),
|
||||
n: common_vendor.t(homeData.value.statistics.totalWeight),
|
||||
o: common_vendor.t(homeData.value.statistics.averagePrice),
|
||||
p: common_vendor.o(($event) => navigateToOrderList("all")),
|
||||
q: common_vendor.f(homeData.value.recentOrders, (order, k0, i0) => {
|
||||
return {
|
||||
a: common_vendor.t(order.orderNo),
|
||||
b: common_vendor.t(order.statusText),
|
||||
c: common_vendor.n(`status-${order.status}`),
|
||||
d: common_vendor.t(order.supplierName),
|
||||
e: common_vendor.t(order.createTime),
|
||||
f: common_vendor.t(order.quantity),
|
||||
g: common_vendor.t(order.weight),
|
||||
h: order.id,
|
||||
i: common_vendor.o(($event) => navigateToOrderDetail(order.id), order.id)
|
||||
};
|
||||
}),
|
||||
r: loading.value,
|
||||
s: common_vendor.o(onRefresh)
|
||||
};
|
||||
};
|
||||
}
|
||||
});
|
||||
wx.createPage(_sfc_main);
|
||||
//# sourceMappingURL=../../../.sourcemap/mp-weixin/pages/index/index.js.map
|
||||
5
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/index/index.json
vendored
Normal file
5
mini_program/client-mp/src/unpackage/dist/dev/mp-weixin/pages/index/index.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"navigationBarTitleText": "活牛采购",
|
||||
"enablePullDownRefresh": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user