feat: 初始化 uni-app 移动端项目

- cashier-mobile: 收银系统移动端(uni-app)
- customer-mobile: 顾客端移动端(uni-app)
- 包含基础页面结构:首页、订单、会员
- 更新 AGENTS.md 配置
This commit is contained in:
2026-06-04 08:31:05 +08:00
parent a8d6fafb71
commit a7e056643e
17 changed files with 620 additions and 25 deletions
+3 -5
View File
@@ -70,12 +70,10 @@ interface UserDTO {
- **组件规范**:组合式 APIsetup 语法)
### cashier-mobile / customer-mobile(移动端)
- **框架**待定(根据需求选择 uni-app、React Native、Flutter 等
- **选型原则**
- uni-app:跨平台、快速开发、适合小程序+H5+App
- React Native:性能要求高、需要原生能力
- Flutter:高性能、自定义 UI
- **框架**uni-appVue3
- **支持平台**:小程序、H5、App
- **包管理器**pnpm(推荐)或 npm
- **UI 框架**uni-ui 或 uview-plus
### 通用规范
1. **代码风格**:遵循项目现有 ESLint/Prettier 配置
+22
View File
@@ -0,0 +1,22 @@
<script setup>
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
onLaunch(() => {
console.log('收银移动端启动')
})
onShow(() => {
console.log('收银移动端显示')
})
onHide(() => {
console.log('收银移动端隐藏')
})
</script>
<style>
/* 全局样式 */
page {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
</style>
+9
View File
@@ -0,0 +1,9 @@
import { createSSRApp } from 'vue'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
+30
View File
@@ -0,0 +1,30 @@
{
"name": "收银系统",
"appid": "__UNI__CASHIER001",
"description": "睿核科技收银系统移动端",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"app-plus": {
"usingComponents": true,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
}
},
"mp-weixin": {
"appid": "",
"setting": {
"urlCheck": false
},
"usingComponents": true
},
"h5": {
"title": "收银系统",
"router": {
"mode": "hash"
}
}
}
+20 -10
View File
@@ -1,15 +1,25 @@
{
"name": "cashier-mobile",
"version": "0.1.0",
"description": "收银系统移动端",
"private": true,
"type": "module",
"version": "1.0.0",
"description": "收银系统移动端 - uni-app",
"main": "main.js",
"scripts": {
"dev": "echo '待配置开发命令'",
"build": "echo '待配置构建命令'",
"lint": "echo '待配置'",
"type-check": "echo '待配置'"
"dev:h5": "uni",
"dev:mp-weixin": "uni --platform mp-weixin",
"dev:app": "uni --platform app",
"build:h5": "uni build",
"build:mp-weixin": "uni build --platform mp-weixin",
"build:app": "uni build --platform app"
},
"dependencies": {},
"devDependencies": {}
"dependencies": {
"@dcloudio/uni-app": "3.0.0",
"vue": "^3.3.0",
"vuex": "^4.1.0"
},
"devDependencies": {
"@dcloudio/types": "^3.3.0",
"@dcloudio/uni-cli-shared": "3.0.0",
"@dcloudio/vite-plugin-uni": "3.0.0",
"vite": "^4.4.0"
}
}
+44
View File
@@ -0,0 +1,44 @@
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "收银台"
}
},
{
"path": "pages/order/order",
"style": {
"navigationBarTitleText": "订单管理"
}
},
{
"path": "pages/member/member",
"style": {
"navigationBarTitleText": "会员管理"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "收银系统",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "收银"
},
{
"pagePath": "pages/order/order",
"text": "订单"
},
{
"pagePath": "pages/member/member",
"text": "会员"
}
]
}
}
+74
View File
@@ -0,0 +1,74 @@
<template>
<view class="container">
<view class="header">
<text class="title">收银台</text>
</view>
<view class="content">
<view class="input-area">
<input
v-model="amount"
type="digit"
placeholder="请输入金额"
class="amount-input"
/>
</view>
<button @click="createOrder" class="submit-btn">创建订单</button>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const amount = ref('')
const createOrder = () => {
if (!amount.value) {
uni.showToast({ title: '请输入金额', icon: 'none' })
return
}
// TODO: 调用创建订单 API
uni.showLoading({ title: '创建中...' })
setTimeout(() => {
uni.hideLoading()
uni.showToast({ title: '创建成功', icon: 'success' })
amount.value = ''
}, 1000)
}
</script>
<style scoped>
.container {
padding: 20rpx;
}
.header {
text-align: center;
margin-bottom: 40rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
}
.input-area {
margin-bottom: 40rpx;
}
.amount-input {
height: 80rpx;
border: 2rpx solid #ddd;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 32rpx;
}
.submit-btn {
background-color: #007AFF;
color: white;
border-radius: 8rpx;
}
</style>
+39
View File
@@ -0,0 +1,39 @@
<template>
<view class="container">
<view class="header">
<text class="title">会员管理</text>
</view>
<view class="member-list">
<view v-for="member in members" :key="member.id" class="member-item">
<text class="member-name">{{ member.name }}</text>
<text class="member-phone">{{ member.phone }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const members = ref([
{ id: 1, name: '张三', phone: '138****8888' },
{ id: 2, name: '李四', phone: '139****9999' }
])
</script>
<style scoped>
.container {
padding: 20rpx;
}
.member-list {
margin-top: 20rpx;
}
.member-item {
display: flex;
justify-content: space-between;
padding: 20rpx;
border-bottom: 1rpx solid #eee;
}
</style>
+45
View File
@@ -0,0 +1,45 @@
<template>
<view class="container">
<view class="header">
<text class="title">订单列表</text>
</view>
<view class="order-list">
<view v-for="order in orders" :key="order.id" class="order-item">
<text class="order-no">{{ order.orderNo }}</text>
<text class="order-amount">¥{{ order.amount }}</text>
<text class="order-status">{{ order.status }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const orders = ref([
{ id: 1, orderNo: 'O202401010001', amount: '199.99', status: '已完成' },
{ id: 2, orderNo: 'O202401010002', amount: '99.99', status: '待支付' }
])
</script>
<style scoped>
.container {
padding: 20rpx;
}
.order-list {
margin-top: 20rpx;
}
.order-item {
display: flex;
justify-content: space-between;
padding: 20rpx;
border-bottom: 1rpx solid #eee;
}
.order-amount {
color: #ff0000;
font-weight: bold;
}
</style>
+22
View File
@@ -0,0 +1,22 @@
<script setup>
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
onLaunch(() => {
console.log('顾客端启动')
})
onShow(() => {
console.log('顾客端显示')
})
onHide(() => {
console.log('顾客端隐藏')
})
</script>
<style>
/* 全局样式 */
page {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
</style>
+9
View File
@@ -0,0 +1,9 @@
import { createSSRApp } from 'vue'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
+30
View File
@@ -0,0 +1,30 @@
{
"name": "顾客端",
"appid": "__UNI__CUSTOMER001",
"description": "睿核科技顾客端移动端",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"app-plus": {
"usingComponents": true,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
}
},
"mp-weixin": {
"appid": "",
"setting": {
"urlCheck": false
},
"usingComponents": true
},
"h5": {
"title": "顾客端",
"router": {
"mode": "hash"
}
}
}
+20 -10
View File
@@ -1,15 +1,25 @@
{
"name": "customer-mobile",
"version": "0.1.0",
"description": "收银系统顾客端",
"private": true,
"type": "module",
"version": "1.0.0",
"description": "顾客端移动端 - uni-app",
"main": "main.js",
"scripts": {
"dev": "echo '待配置开发命令'",
"build": "echo '待配置构建命令'",
"lint": "echo '待配置'",
"type-check": "echo '待配置'"
"dev:h5": "uni",
"dev:mp-weixin": "uni --platform mp-weixin",
"dev:app": "uni --platform app",
"build:h5": "uni build",
"build:mp-weixin": "uni build --platform mp-weixin",
"build:app": "uni build --platform app"
},
"dependencies": {},
"devDependencies": {}
"dependencies": {
"@dcloudio/uni-app": "3.0.0",
"vue": "^3.3.0",
"vuex": "^4.1.0"
},
"devDependencies": {
"@dcloudio/types": "^3.3.0",
"@dcloudio/uni-cli-shared": "3.0.0",
"@dcloudio/vite-plugin-uni": "3.0.0",
"vite": "^4.4.0"
}
}
+44
View File
@@ -0,0 +1,44 @@
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/order/order",
"style": {
"navigationBarTitleText": "我的订单"
}
},
{
"path": "pages/member/member",
"style": {
"navigationBarTitleText": "会员中心"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "顾客端",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"list": [
{
"pagePath": "pages/index/index",
"text": "首页"
},
{
"pagePath": "pages/order/order",
"text": "订单"
},
{
"pagePath": "pages/member/member",
"text": "我的"
}
]
}
}
+80
View File
@@ -0,0 +1,80 @@
<template>
<view class="container">
<view class="header">
<text class="title">欢迎光临</text>
</view>
<view class="content">
<view class="menu-list">
<view v-for="item in menuList" :key="item.id" class="menu-item" @click="goToDetail(item)">
<image :src="item.image" class="menu-image" mode="aspectFill" />
<text class="menu-name">{{ item.name }}</text>
<text class="menu-price">¥{{ item.price }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const menuList = ref([
{ id: 1, name: '招牌奶茶', price: '18.00', image: '/static/logo.png' },
{ id: 2, name: '美式咖啡', price: '22.00', image: '/static/logo.png' },
{ id: 3, name: '芝士蛋糕', price: '28.00', image: '/static/logo.png' }
])
const goToDetail = (item) => {
uni.navigateTo({
url: `/pages/order/order?id=${item.id}`
})
}
</script>
<style scoped>
.container {
padding: 20rpx;
}
.header {
text-align: center;
margin-bottom: 40rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
}
.menu-list {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.menu-item {
width: calc(50% - 10rpx);
background: #fff;
border-radius: 12rpx;
overflow: hidden;
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
}
.menu-image {
width: 100%;
height: 200rpx;
}
.menu-name {
display: block;
padding: 10rpx;
font-size: 28rpx;
}
.menu-price {
display: block;
padding: 0 10rpx 10rpx;
color: #ff0000;
font-weight: bold;
}
</style>
+84
View File
@@ -0,0 +1,84 @@
<template>
<view class="container">
<view class="header">
<text class="title">会员中心</text>
</view>
<view class="member-info">
<view class="avatar-section">
<image src="/static/logo.png" class="avatar" />
<text class="nickname">张三</text>
<text class="level">黄金会员</text>
</view>
<view class="stats">
<view class="stat-item">
<text class="stat-value">100</text>
<text class="stat-label">积分</text>
</view>
<view class="stat-item">
<text class="stat-value">5</text>
<text class="stat-label">优惠券</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
// 会员中心逻辑
</script>
<style scoped>
.container {
padding: 20rpx;
}
.member-info {
text-align: center;
}
.avatar-section {
margin-bottom: 40rpx;
}
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
margin-bottom: 20rpx;
}
.nickname {
display: block;
font-size: 32rpx;
font-weight: bold;
margin-bottom: 10rpx;
}
.level {
display: block;
color: #999;
}
.stats {
display: flex;
justify-content: space-around;
margin-top: 40rpx;
}
.stat-item {
text-align: center;
}
.stat-value {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #007AFF;
}
.stat-label {
display: block;
color: #999;
margin-top: 10rpx;
}
</style>
+45
View File
@@ -0,0 +1,45 @@
<template>
<view class="container">
<view class="header">
<text class="title">我的订单</text>
</view>
<view class="order-list">
<view v-for="order in orders" :key="order.id" class="order-item">
<text class="order-no">{{ order.orderNo }}</text>
<text class="order-amount">¥{{ order.amount }}</text>
<text class="order-status">{{ order.status }}</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
const orders = ref([
{ id: 1, orderNo: 'O202401010001', amount: '199.99', status: '已完成' },
{ id: 2, orderNo: 'O202401010002', amount: '99.99', status: '待支付' }
])
</script>
<style scoped>
.container {
padding: 20rpx;
}
.order-list {
margin-top: 20rpx;
}
.order-item {
display: flex;
justify-content: space-between;
padding: 20rpx;
border-bottom: 1rpx solid #eee;
}
.order-amount {
color: #ff0000;
font-weight: bold;
}
</style>