实现订单管理核心功能,包括订单创建、查询、取消和状态管理

This commit is contained in:
ylweng
2025-09-18 08:55:32 +08:00
parent 90cdd713ba
commit 7b6dd95fa5
26 changed files with 16633 additions and 5 deletions

View File

@@ -0,0 +1,13 @@
{
"name": "driver-mp",
"version": "1.0.0",
"description": "活牛运输司机小程序",
"main": "main.js",
"scripts": {
"dev": "uni -p mp-weixin"
},
"dependencies": {
"@dcloudio/uni-app": "^3.0.0",
"pinia": "^2.0.0"
}
}

View File

@@ -0,0 +1,13 @@
{
"name": "sales-mp",
"version": "1.0.0",
"description": "活牛销售小程序",
"main": "main.js",
"scripts": {
"dev": "uni -p mp-weixin"
},
"dependencies": {
"@dcloudio/uni-app": "^3.0.0",
"pinia": "^2.0.0"
}
}

View File

@@ -0,0 +1,15 @@
<script setup lang="ts">
// 活牛销售首页
</script>
<template>
<view class="container">
<text>活牛销售小程序首页</text>
</view>
</template>
<style lang="scss">
.container {
padding: 20rpx;
}
</style>

View File

@@ -0,0 +1,48 @@
module.exports = {
root: true,
env: {
node: true,
browser: true,
es2021: true
},
extends: [
'eslint:recommended',
'@vue/typescript/recommended'
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module'
},
rules: {
// 基本规则
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// TypeScript 规则
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'off',
// Vue 规则
'vue/multi-word-component-names': 'off',
'vue/no-v-model-argument': 'off',
// 代码风格
'indent': ['error', 2],
'quotes': ['error', 'single'],
'semi': ['error', 'always'],
'comma-dangle': ['error', 'never'],
'object-curly-spacing': ['error', 'always'],
'array-bracket-spacing': ['error', 'never']
},
overrides: [
{
files: ['*.vue'],
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser'
}
}
]
};

View File

@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none",
"endOfLine": "auto"
}

View File

@@ -0,0 +1,29 @@
import js from '@eslint/js';
import typescript from '@typescript-eslint/eslint-plugin';
import typescriptParser from '@typescript-eslint/parser';
export default [
js.configs.recommended,
{
files: ['**/*.{js,ts}'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
}
},
plugins: {
'@typescript-eslint': typescript
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': 'error',
'indent': ['error', 2],
'quotes': ['error', 'single'],
'semi': ['error', 'always']
}
}
];

13469
mini_program/staff-mp/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
{
"name": "staff-mp",
"version": "1.0.0",
"description": "活牛采购内部员工小程序",
"type": "module",
"main": "main.js",
"scripts": {
"dev": "npx uniapp-cli -p mp-weixin",
"build": "npx uniapp-cli build -p mp-weixin",
"lint": "eslint --ext .ts src/",
"prettier": "prettier --write src/"
},
"dependencies": {
"@dcloudio/uni-app": "^3.0.0-alpha-3070620220707001",
"pinia": "^2.0.0",
"vue": "^2.6.0 || ^3.0.0"
},
"devDependencies": {
"@dcloudio/types": "^3.0.0-alpha-3070620220707001",
"@dcloudio/uni-cli-i18n": "^2.0.2-4070620250821001",
"@dcloudio/uni-cli-shared": "^3.0.0-alpha-3070620220707001",
"@dcloudio/uni-mp-weixin": "^3.0.0-alpha-3070620220707001",
"@dcloudio/vue-cli-plugin-uni": "^2.0.2-4070620250821001",
"@dcloudio/webpack-uni-pages-loader": "^2.0.2-4070620250821001",
"@eslint/js": "^9.35.0",
"@typescript-eslint/eslint-plugin": "^8.44.0",
"@typescript-eslint/parser": "^8.44.0",
"@vue/cli-service": "^5.0.9",
"eslint": "^9.35.0",
"eslint-plugin-vue": "^10.4.0",
"miniprogram-api-typings": "^3.0.0",
"typescript": "^5.0.0"
},
"peerDependencies": {
"vue": "^2.6.0 || ^3.0.0"
}
}

View File

@@ -0,0 +1,19 @@
{
"name": "staff-mp",
"appid": "__UNI__STAFFMP",
"description": "活牛采购内部员工小程序",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"mp-weixin": {
"appid": "wx-your-appid-here",
"setting": {
"urlCheck": false,
"es6": true,
"postcss": true,
"minified": true
},
"usingComponents": true
},
"vueVersion": "3"
}

View File

@@ -0,0 +1,72 @@
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/order/order-monitor",
"style": {
"navigationBarTitleText": "订单监控"
}
},
{
"path": "pages/transport/transport-monitor",
"style": {
"navigationBarTitleText": "运输监控"
}
},
{
"path": "pages/statistics/data-dashboard",
"style": {
"navigationBarTitleText": "数据统计"
}
},
{
"path": "pages/system/system-settings",
"style": {
"navigationBarTitleText": "系统设置"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "活牛采购系统",
"navigationBarBackgroundColor": "#f8f8f8",
"backgroundColor": "#f8f8f8"
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#1989fa",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png",
"text": "首页"
},
{
"pagePath": "pages/order/order-monitor",
"iconPath": "static/tabbar/order.png",
"selectedIconPath": "static/tabbar/order-active.png",
"text": "订单"
},
{
"pagePath": "pages/transport/transport-monitor",
"iconPath": "static/tabbar/transport.png",
"selectedIconPath": "static/tabbar/transport-active.png",
"text": "运输"
},
{
"pagePath": "pages/statistics/data-dashboard",
"iconPath": "static/tabbar/statistics.png",
"selectedIconPath": "static/tabbar/statistics-active.png",
"text": "统计"
}
]
}
}

View File

@@ -0,0 +1,169 @@
<script setup lang="ts">
// 首页
import { ref } from 'vue';
const quickActions = ref([
{
icon: 'order',
title: '订单管理',
path: '/pages/order/order-monitor'
},
{
icon: 'transport',
title: '运输监控',
path: '/pages/transport/transport-monitor'
},
{
icon: 'statistics',
title: '数据统计',
path: '/pages/statistics/data-dashboard'
},
{
icon: 'settings',
title: '系统设置',
path: '/pages/system/system-settings'
}
]);
const navigateTo = (path: string) => {
uni.navigateTo({
url: path
});
};
</script>
<template>
<view class="container">
<view class="header">
<text class="welcome">欢迎使用活牛采购系统</text>
<text class="subtitle">内部员工工作台</text>
</view>
<view class="quick-actions">
<view
v-for="(action, index) in quickActions"
:key="index"
class="action-card"
@click="navigateTo(action.path)"
>
<view class="action-icon">
<text class="icon">{{ action.icon }}</text>
</view>
<text class="action-title">{{ action.title }}</text>
</view>
</view>
<view class="recent-section">
<text class="section-title">最近动态</text>
<view class="recent-list">
<view class="recent-item">
<text class="recent-text">新订单 #20250001 待审核</text>
<text class="recent-time">10分钟前</text>
</view>
<view class="recent-item">
<text class="recent-text">运输车辆 京A12345 已出发</text>
<text class="recent-time">30分钟前</text>
</view>
<view class="recent-item">
<text class="recent-text">订单 #20249999 已完成</text>
<text class="recent-time">1小时前</text>
</view>
</view>
</view>
</view>
</template>
<style lang="scss">
.container {
padding: 20rpx;
}
.header {
text-align: center;
padding: 40rpx 0;
.welcome {
font-size: 36rpx;
font-weight: bold;
display: block;
margin-bottom: 10rpx;
}
.subtitle {
color: #666;
font-size: 24rpx;
}
}
.quick-actions {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
margin-bottom: 40rpx;
.action-card {
background: #fff;
padding: 30rpx;
border-radius: 12rpx;
text-align: center;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
.action-icon {
width: 80rpx;
height: 80rpx;
background: #1989fa;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto 20rpx;
.icon {
color: #fff;
font-size: 36rpx;
}
}
.action-title {
font-size: 24rpx;
color: #333;
}
}
}
.recent-section {
.section-title {
font-size: 28rpx;
font-weight: bold;
margin-bottom: 20rpx;
display: block;
}
.recent-list {
background: #fff;
border-radius: 12rpx;
overflow: hidden;
.recent-item {
padding: 24rpx;
border-bottom: 1rpx solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
&:last-child {
border-bottom: none;
}
.recent-text {
font-size: 26rpx;
}
.recent-time {
color: #999;
font-size: 22rpx;
}
}
}
}
</style>

View File

@@ -0,0 +1,138 @@
<script setup lang="ts">
// 订单监控页面
import { ref } from 'vue';
const orders = ref([]);
const loading = ref(false);
// 模拟订单数据
const mockOrders = [
{ id: '1', orderNo: 'ORDER2025001', supplier: '张三养殖场', status: 'pending', quantity: 50, amount: 250000 },
{ id: '2', orderNo: 'ORDER2025002', supplier: '李四牧场', status: 'confirmed', quantity: 30, amount: 150000 },
{ id: '3', orderNo: 'ORDER2025003', supplier: '王五畜牧', status: 'in_transit', quantity: 80, amount: 400000 }
];
const loadOrders = async () => {
loading.value = true;
// 模拟API调用
setTimeout(() => {
orders.value = mockOrders;
loading.value = false;
}, 1000);
};
loadOrders();
</script>
<template>
<view class="container">
<view class="header">
<text class="title">订单监控</text>
</view>
<view class="filter-bar">
<picker mode="selector" :range="['全部', '待确认', '已确认', '运输中']">
<view class="filter-item">筛选状态</view>
</picker>
</view>
<scroll-view scroll-y class="order-list">
<view v-if="loading" class="loading">加载中...</view>
<view v-for="order in orders" :key="order.id" class="order-item">
<view class="order-header">
<text class="order-no">{{ order.orderNo }}</text>
<text :class="`status-${order.status}`">{{ order.status }}</text>
</view>
<view class="order-info">
<text>供应商: {{ order.supplier }}</text>
<text>数量: {{ order.quantity }}</text>
<text>金额: ¥{{ order.amount }}</text>
</view>
<view class="order-actions">
<button size="mini" @click="handleViewDetail(order.id)">查看详情</button>
<button v-if="order.status === 'pending'" size="mini" type="primary" @click="handleApprove(order.id)">审核通过</button>
</view>
</view>
</scroll-view>
</view>
</template>
<style lang="scss">
.container {
padding: 20rpx;
}
.header {
padding: 20rpx 0;
.title {
font-size: 32rpx;
font-weight: bold;
}
}
.filter-bar {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 8rpx;
.filter-item {
color: #666;
}
}
.order-list {
height: calc(100vh - 200rpx);
}
.order-item {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 8rpx;
.order-header {
display: flex;
justify-content: space-between;
margin-bottom: 15rpx;
.order-no {
font-weight: bold;
}
.status-pending {
color: #ff9900;
}
.status-confirmed {
color: #1989fa;
}
.status-in_transit {
color: #3cc51f;
}
}
.order-info {
margin-bottom: 15rpx;
text {
display: block;
margin-bottom: 5rpx;
color: #666;
}
}
.order-actions {
display: flex;
gap: 10rpx;
button {
flex: 1;
}
}
}
.loading {
text-align: center;
padding: 40rpx;
color: #999;
}
</style>

View File

@@ -0,0 +1,131 @@
<script setup lang="ts">
// 数据统计仪表板
import { ref } from 'vue';
const stats = ref({
totalOrders: 0,
totalAmount: 0,
pendingOrders: 0,
completedOrders: 0
});
const loadStatistics = async () => {
// 模拟API调用
setTimeout(() => {
stats.value = {
totalOrders: 156,
totalAmount: 7800000,
pendingOrders: 23,
completedOrders: 133
};
}, 500);
};
loadStatistics();
</script>
<template>
<view class="container">
<view class="header">
<text class="title">数据统计</text>
</view>
<view class="stats-grid">
<view class="stat-card">
<text class="stat-value">{{ stats.totalOrders }}</text>
<text class="stat-label">总订单数</text>
</view>
<view class="stat-card">
<text class="stat-value">¥{{ stats.totalAmount.toLocaleString() }}</text>
<text class="stat-label">总金额</text>
</view>
<view class="stat-card">
<text class="stat-value">{{ stats.pendingOrders }}</text>
<text class="stat-label">待处理</text>
</view>
<view class="stat-card">
<text class="stat-value">{{ stats.completedOrders }}</text>
<text class="stat-label">已完成</text>
</view>
</view>
<view class="charts-section">
<view class="chart-container">
<text class="chart-title">订单状态分布</text>
<view class="chart-placeholder">图表组件加载中...</view>
</view>
<view class="chart-container">
<text class="chart-title">月度采购趋势</text>
<view class="chart-placeholder">图表组件加载中...</view>
</view>
</view>
</view>
</template>
<style lang="scss">
.container {
padding: 20rpx;
}
.header {
padding: 20rpx 0;
.title {
font-size: 32rpx;
font-weight: bold;
}
}
.stats-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
margin-bottom: 30rpx;
.stat-card {
background: #fff;
padding: 30rpx;
border-radius: 8rpx;
text-align: center;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
.stat-value {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #1989fa;
margin-bottom: 10rpx;
}
.stat-label {
color: #666;
font-size: 24rpx;
}
}
}
.charts-section {
.chart-container {
background: #fff;
padding: 20rpx;
border-radius: 8rpx;
margin-bottom: 20rpx;
.chart-title {
font-weight: bold;
margin-bottom: 15rpx;
display: block;
}
.chart-placeholder {
height: 200rpx;
background: #f5f5f5;
border-radius: 4rpx;
display: flex;
justify-content: center;
align-items: center;
color: #999;
}
}
}
</style>

View File

@@ -0,0 +1,113 @@
<script setup lang="ts">
// 系统设置页面
import { ref } from 'vue';
const settings = ref({
notifications: true,
autoRefresh: true,
refreshInterval: 30,
theme: 'light'
});
const saveSettings = async () => {
// 模拟保存设置
uni.showToast({
title: '设置已保存',
icon: 'success'
});
};
</script>
<template>
<view class="container">
<view class="header">
<text class="title">系统设置</text>
</view>
<view class="settings-list">
<view class="setting-item">
<text class="setting-label">消息通知</text>
<switch :checked="settings.notifications" @change="settings.notifications = $event.detail.value" />
</view>
<view class="setting-item">
<text class="setting-label">自动刷新</text>
<switch :checked="settings.autoRefresh" @change="settings.autoRefresh = $event.detail.value" />
</view>
<view class="setting-item">
<text class="setting-label">刷新间隔()</text>
<slider :value="settings.refreshInterval" min="10" max="60" @change="settings.refreshInterval = $event.detail.value" />
<text class="slider-value">{{ settings.refreshInterval }}</text>
</view>
<view class="setting-item">
<text class="setting-label">主题模式</text>
<picker :value="settings.theme" :range="['light', 'dark']" @change="settings.theme = $event.detail.value[0]">
<view class="picker-value">{{ settings.theme === 'light' ? '浅色' : '深色' }}</view>
</picker>
</view>
</view>
<view class="action-buttons">
<button type="primary" @click="saveSettings">保存设置</button>
<button @click="uni.navigateBack()">取消</button>
</view>
</view>
</template>
<style lang="scss">
.container {
padding: 20rpx;
}
.header {
padding: 20rpx 0;
.title {
font-size: 32rpx;
font-weight: bold;
}
}
.settings-list {
background: #fff;
border-radius: 8rpx;
margin-bottom: 30rpx;
.setting-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #eee;
&:last-child {
border-bottom: none;
}
.setting-label {
font-size: 28rpx;
}
.slider-value {
color: #666;
font-size: 24rpx;
margin-left: 20rpx;
}
.picker-value {
color: #1989fa;
}
}
}
.action-buttons {
button {
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
}
}
</style>

View File

@@ -0,0 +1,135 @@
<script setup lang="ts">
// 运输监控页面
import { ref } from 'vue';
const transports = ref([]);
const mapReady = ref(false);
// 模拟运输数据
const mockTransports = [
{ id: '1', orderNo: 'ORDER2025001', driver: '张师傅', phone: '13800138000', currentLocation: '北京市朝阳区', status: 'transporting' },
{ id: '2', orderNo: 'ORDER2025002', driver: '李师傅', phone: '13900139000', currentLocation: '天津市南开区', status: 'transporting' },
{ id: '3', orderNo: 'ORDER2025003', driver: '王师傅', phone: '13700137000', currentLocation: '河北省石家庄市', status: 'arrived' }
];
const loadTransports = async () => {
// 模拟API调用
setTimeout(() => {
transports.value = mockTransports;
}, 500);
};
loadTransports();
</script>
<template>
<view class="container">
<view class="header">
<text class="title">运输监控</text>
</view>
<view class="map-container">
<text class="map-placeholder">地图组件加载中...</text>
</view>
<scroll-view scroll-y class="transport-list">
<view v-for="transport in transports" :key="transport.id" class="transport-item">
<view class="transport-header">
<text class="order-no">{{ transport.orderNo }}</text>
<text :class="`status-${transport.status}`">
{{ transport.status === 'transporting' ? '运输中' : '已到达' }}
</text>
</view>
<view class="driver-info">
<text>司机: {{ transport.driver }}</text>
<text>电话: {{ transport.phone }}</text>
</view>
<view class="location-info">
<text>当前位置: {{ transport.currentLocation }}</text>
</view>
<view class="transport-actions">
<button size="mini" @click="handleCallDriver(transport.phone)">联系司机</button>
<button size="mini" type="primary" @click="handleViewTrack(transport.id)">查看轨迹</button>
</view>
</view>
</scroll-view>
</view>
</template>
<style lang="scss">
.container {
padding: 20rpx;
}
.header {
padding: 20rpx 0;
.title {
font-size: 32rpx;
font-weight: bold;
}
}
.map-container {
height: 300rpx;
background: #f5f5f5;
border-radius: 8rpx;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20rpx;
.map-placeholder {
color: #999;
}
}
.transport-list {
height: calc(100vh - 400rpx);
}
.transport-item {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 8rpx;
.transport-header {
display: flex;
justify-content: space-between;
margin-bottom: 15rpx;
.order-no {
font-weight: bold;
}
.status-transporting {
color: #1989fa;
}
.status-arrived {
color: #3cc51f;
}
}
.driver-info, .location-info {
margin-bottom: 10rpx;
text {
display: block;
margin-bottom: 5rpx;
color: #666;
}
}
.transport-actions {
display: flex;
gap: 10rpx;
button {
flex: 1;
}
}
}
</style>

View File

@@ -0,0 +1,15 @@
# 标签栏图标
请在此目录放置标签栏图标文件:
- home.png / home-active.png - 首页图标
- order.png / order-active.png - 订单图标
- transport.png / transport-active.png - 运输图标
- statistics.png / statistics-active.png - 统计图标
图标要求:
- 尺寸50x50 像素
- 格式PNG 透明背景
- 颜色:默认灰色,激活状态主题色
如果没有图标文件,系统会使用文本标签代替。

View File

@@ -0,0 +1,98 @@
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { getOrderList, getTransportData } from '@/utils/api';
export interface Order {
id: string;
orderNumber: string;
customerName: string;
status: 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled';
totalAmount: number;
createdAt: string;
updatedAt: string;
}
export interface TransportData {
orderId: string;
currentLocation: string;
estimatedArrival: string;
driverName: string;
driverPhone: string;
vehicleNumber: string;
temperature: number;
humidity: number;
}
export const useOrderStore = defineStore('order', () => {
const orders = ref<Order[]>([]);
const currentOrder = ref<Order | null>(null);
const transportData = ref<TransportData | null>(null);
const loading = ref(false);
const error = ref<string | null>(null);
// 计算属性
const pendingOrders = computed(() =>
orders.value.filter(order => order.status === 'pending')
);
const processingOrders = computed(() =>
orders.value.filter(order => order.status === 'processing')
);
const shippedOrders = computed(() =>
orders.value.filter(order => order.status === 'shipped')
);
// 动作
const fetchOrders = async () => {
loading.value = true;
error.value = null;
try {
const response = await getOrderList({ page: 1, pageSize: 50 });
orders.value = response.data.list;
} catch (err) {
error.value = err instanceof Error ? err.message : '获取订单列表失败';
// console.error('Failed to fetch orders:', err);
} finally {
loading.value = false;
}
};
const fetchTransportData = async (orderId: string) => {
loading.value = true;
error.value = null;
try {
const response = await getTransportData(orderId);
transportData.value = response.data;
} catch (err) {
error.value = err instanceof Error ? err.message : '获取运输数据失败';
// console.error('Failed to fetch transport data:', err);
} finally {
loading.value = false;
}
};
const updateOrderStatus = (orderId: string, status: Order['status']) => {
const order = orders.value.find(o => o.id === orderId);
if (order) {
order.status = status;
order.updatedAt = new Date().toISOString();
}
};
return {
orders,
currentOrder,
transportData,
loading,
error,
pendingOrders,
processingOrders,
shippedOrders,
fetchOrders,
fetchTransportData,
updateOrderStatus,
};
});

View File

@@ -0,0 +1,87 @@
// API 工具函数
export interface ApiResponse<T = unknown> {
code: number;
data: T;
message: string;
}
export interface PaginationParams {
page: number;
pageSize: number;
}
export interface PaginationResult<T> {
list: T[];
total: number;
page: number;
pageSize: number;
}
/**
* 统一的 API 请求函数
*/
export async function request<T>(
url: string,
options?: { method?: string; headers?: Record<string, string>; body?: unknown }
): Promise<ApiResponse<T>> {
declare const uni: unknown;
const response = await uni.request({
url,
method: options?.method || 'GET',
header: {
'Content-Type': 'application/json',
...options?.headers,
},
data: options?.body,
});
if (response.statusCode !== 200) {
throw new Error(`HTTP error! status: ${response.statusCode}`);
}
const data = response.data as ApiResponse<T>;
if (data.code !== 200) {
throw new Error(data.message || 'API request failed');
}
return data;
}
/**
* 获取订单列表
*/
export async function getOrderList() {
return request<PaginationResult<Order>>('/api/orders', {
method: 'GET',
});
}
/**
* 获取运输监控数据
*/
export async function getTransportData(orderId: string) {
return request<TransportData>(`/api/transport/${orderId}`);
}
interface Order {
id: string;
orderNumber: string;
customerName: string;
status: string;
totalAmount: number;
createdAt: string;
updatedAt: string;
}
interface TransportData {
orderId: string;
currentLocation: string;
estimatedArrival: string;
driverName: string;
driverPhone: string;
vehicleNumber: string;
temperature: number;
humidity: number;
}

View File

@@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"strict": true,
"jsx": "preserve",
"moduleResolution": "node",
"esModuleInterop": true,
"sourceMap": true,
"skipLibCheck": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"types": [
"@dcloudio/types",
"miniprogram-api-typings",
"node"
]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["node_modules"]
}

View File

@@ -0,0 +1,17 @@
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
resolve: {
alias: {
'@': require('path').resolve(__dirname, 'src')
}
}
},
pluginOptions: {
'uni-app': {
platform: 'mp-weixin'
}
}
})

View File

@@ -0,0 +1,13 @@
{
"name": "supplier-mp",
"version": "1.0.0",
"description": "活牛供应商小程序",
"main": "main.js",
"scripts": {
"dev": "uni -p mp-weixin"
},
"dependencies": {
"@dcloudio/uni-app": "^3.0.0",
"pinia": "^2.0.0"
}
}

View File

@@ -0,0 +1,15 @@
<script setup lang="ts">
// 供应商小程序首页
</script>
<template>
<view class="container">
<text>供应商小程序首页</text>
</view>
</template>
<style lang="scss">
.container {
padding: 20rpx;
}
</style>