薛秀芸 1 месяц назад
Сommit
c7fa0c1da9

+ 48 - 0
App.uvue

@@ -0,0 +1,48 @@
+<script lang="uts">
+	// #ifdef APP-ANDROID || APP-HARMONY
+	let firstBackTime = 0
+	// #endif
+	export default {
+		onLaunch() {
+			console.log('App Launch')
+		},
+		onShow() {
+			console.log('App Show')
+		},
+		onHide() {
+			console.log('App Hide')
+		},
+		// #ifdef APP-ANDROID || APP-HARMONY
+		onLastPageBackPress() {
+			console.log('App LastPageBackPress')
+			if (firstBackTime == 0) {
+				uni.showToast({
+					title: '再按一次退出应用',
+					position: 'bottom',
+				})
+				firstBackTime = Date.now()
+				setTimeout(() => {
+					firstBackTime = 0
+				}, 2000)
+			} else if (Date.now() - firstBackTime < 2000) {
+				firstBackTime = Date.now()
+				uni.exit()
+			}
+		},
+		// #endif
+		onExit() {
+			console.log('App Exit')
+		},
+	}
+</script>
+
+<style>
+	/*每个页面公共css */
+	.uni-row {
+		flex-direction: row;
+	}
+
+	.uni-column {
+		flex-direction: column;
+	}
+</style>

+ 103 - 0
components/CustomBottomNav.uvue

@@ -0,0 +1,103 @@
+<template>
+	<view class="bottom-nav">
+		    <!-- 底座(可加背景色或阴影) -->
+		    <view class="tabbar-platform"></view>
+		<view v-for="(item, index) in tabs" :key="index" class="nav-item" :class="{ active: currentIndex === index }"
+			@click="handleClick(index)">
+			<text class="nav-text">{{ item.text }}</text>
+		</view>
+	</view>
+</template>
+
+<script setup lang="ts">
+	// Props & Emits
+	interface TabItem {
+		text : string;
+	}
+
+	interface Props {
+		currentIndex : number;
+	}
+
+	const props = defineProps<Props>();
+	const emit = defineEmits<{
+		(e : 'change', index : number) : void;
+	}>();
+
+	// 配置数据(可从 props 接收)
+	const tabs : TabItem[] = [
+		{ text: '小丁' },
+		{ text: '理疗' },
+		{ text: '预约' },
+		{ text: '商户' },
+		{ text: '我的' }
+	];
+
+	// 方法
+	const handleClick = (index : number) => {
+		emit('change', index);
+	};
+</script>
+
+<style scoped>
+	.tabbar-platform{
+		background-color: #ffffff;
+		box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
+		height: 100rpx;
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		right: 0;
+	}
+	/* 底部导航容器 */
+	.bottom-nav {
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		display: flex;
+		flex-direction: row;
+		justify-content: space-around;
+		align-items: flex-end;
+		padding: 10rpx 0 ;
+		
+		z-index: 1;
+	}
+
+	/* 单个导航项 */
+	.nav-item {
+		width: 80rpx;
+		height: 80rpx;
+		border-radius: 50%;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		background-color: #ffa500;
+		/* 橙色背景 */
+		color: #ffffff;
+		/* 白色文字 */
+		font-size: 26rpx;
+		font-weight: bold;
+		transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
+		position: relative;
+	}
+
+	/* 选中状态 */
+	.nav-item.active {
+		width: 110rpx;
+		height: 110rpx;
+		transform: translateY(-10rpx);
+		/* 上浮 */
+		z-index: 10;
+		background-color: #ffffff;
+		/* 白底 */
+		color: #ffa500;
+		/* 橙色文字 */
+		box-shadow: 0 8rpx 20rpx rgba(255, 165, 0, 0.4);
+	}
+
+	/* 文字样式 */
+	.nav-text {
+		line-height: 1;
+	}
+</style>

+ 20 - 0
index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+	<head>
+		<meta charset="UTF-8" />
+		<script>
+			var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+				CSS.supports('top: constant(a)'))
+			document.write(
+				'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+				(coverSupport ? ', viewport-fit=cover' : '') + '" />')
+		</script>
+		<title>小丁到家</title>
+		<!--preload-links-->
+		<!--app-context-->
+	</head>
+	<body>
+		<div id="app"><!--app-html--></div>
+		<script type="module" src="/main"></script>
+	</body>
+</html>

+ 9 - 0
main.uts

@@ -0,0 +1,9 @@
+import App from './App.uvue'
+
+import { createSSRApp } from 'vue'
+export function createApp() {
+	const app = createSSRApp(App)
+	return {
+		app
+	}
+}

+ 43 - 0
manifest.json

@@ -0,0 +1,43 @@
+{
+    "name" : "小丁到家",
+    "appid" : "__UNI__9F955ED",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "uni-app-x" : {},
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "3",
+    "app" : {
+        "distribute" : {
+            "icons" : {
+                "android" : {
+                    "hdpi" : "",
+                    "xhdpi" : "",
+                    "xxhdpi" : "",
+                    "xxxhdpi" : ""
+                }
+            }
+        }
+    }
+}

+ 62 - 0
pages.json

@@ -0,0 +1,62 @@
+{
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://doc.dcloud.net.cn/uni-app-x/collocation/pagesjson.html
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "首页"
+			}
+		},
+		{
+			"path": "pages/index/my",
+			"style": {
+				"navigationBarTitleText": "我的"
+			}
+		},
+		{
+			"path": "pages/index/therapy",
+			"style": {
+				"navigationBarTitleText": "理疗"
+			}
+		},
+		{
+			"path": "pages/index/order",
+			"style": {
+				"navigationBarTitleText": "预约"
+			}
+		},
+		{
+			"path": "pages/index/merchant",
+			"style": {
+				"navigationBarTitleText": "商户"
+			}
+		}
+	],
+
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "小丁到家--上门按摩",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"backgroundColor": "#F8F8F8"
+	},
+	"tabBar": {
+	    "list": [
+	      {
+	        "pagePath": "pages/index/index",
+	        "text": "首页"
+	      },{
+			  "pagePath": "pages/index/therapy",
+			  "text": "理疗"
+		  },{
+			  "pagePath": "pages/index/order",
+			  "text": "预约"
+		  },{
+			  "pagePath": "pages/index/merchant",
+			  "text": "商户"
+		  },
+	      {
+	        "pagePath": "pages/index/my",
+	        "text": "我的"
+	      },
+	    ]
+	"uniIdRouter": {}
+}

+ 52 - 0
pages/index/index.uvue

@@ -0,0 +1,52 @@
+<template>
+  <view class="page">
+    <view class="content">当前页面:{{ currentTabName }}</view>
+
+    <!-- 自定义底部导航 -->
+    <CustomBottomNav 
+      :current-index="currentTab" 
+      @change="onTabChange" 
+    />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue';
+import CustomBottomNav from '@/components/CustomBottomNav.uvue';
+
+// 当前选中索引
+const currentTab = ref(0);
+
+// 根据索引获取名称(用于演示)
+const tabNames = ['小丁', '理疗', '预约', '商户', '我的'];
+const currentTabName = computed(() => tabNames[currentTab.value]);
+
+// 切换 Tab
+const onTabChange = (index: number) => {
+  currentTab.value = index;
+
+  // 可选:跳转到对应 tabBar 页面
+  const pages = [
+    '/pages/index/index',
+    '/pages/index/therapy',
+    '/pages/index/order',
+    '/pages/index/merchant',
+    '/pages/index/my'
+  ];
+  uni.switchTab({ url: pages[index] });
+};
+</script>
+
+<style scoped>
+.page {
+  min-height: 100vh;
+  padding-bottom: 100rpx; /* 防止内容被遮挡 */
+  background-color: #f8f8f8;
+  padding: 20rpx;
+}
+
+.content {
+  font-size: 32rpx;
+  color: #333;
+}
+</style>

+ 52 - 0
pages/index/merchant.uvue

@@ -0,0 +1,52 @@
+<template>
+  <view class="page">
+    <view class="content">当前页面:{{ currentTabName }}</view>
+
+    <!-- 自定义底部导航 -->
+    <CustomBottomNav 
+      :current-index="currentTab" 
+      @change="onTabChange" 
+    />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue';
+import CustomBottomNav from '@/components/CustomBottomNav.uvue';
+
+// 当前选中索引
+const currentTab = ref(3);
+
+// 根据索引获取名称(用于演示)
+const tabNames = ['小丁', '理疗', '预约', '商户', '我的'];
+const currentTabName = computed(() => tabNames[currentTab.value]);
+
+// 切换 Tab
+const onTabChange = (index: number) => {
+  currentTab.value = index;
+
+  // 可选:跳转到对应 tabBar 页面
+  const pages = [
+    '/pages/index/index',
+    '/pages/index/therapy',
+    '/pages/index/order',
+    '/pages/index/merchant',
+    '/pages/index/my'
+  ];
+  uni.switchTab({ url: pages[index] });
+};
+</script>
+
+<style scoped>
+.page {
+  min-height: 100vh;
+  padding-bottom: 100rpx; /* 防止内容被遮挡 */
+  background-color: #f8f8f8;
+  padding: 20rpx;
+}
+
+.content {
+  font-size: 32rpx;
+  color: #333;
+}
+</style>

+ 52 - 0
pages/index/my.uvue

@@ -0,0 +1,52 @@
+<template>
+  <view class="page">
+    <view class="content">当前页面:{{ currentTabName }}</view>
+
+    <!-- 自定义底部导航 -->
+    <CustomBottomNav 
+      :current-index="currentTab" 
+      @change="onTabChange" 
+    />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue';
+import CustomBottomNav from '@/components/CustomBottomNav.uvue';
+
+// 当前选中索引
+const currentTab = ref(4);
+
+// 根据索引获取名称(用于演示)
+const tabNames = ['小丁', '理疗', '预约', '商户', '我的'];
+const currentTabName = computed(() => tabNames[currentTab.value]);
+
+// 切换 Tab
+const onTabChange = (index: number) => {
+  currentTab.value = index;
+
+  // 可选:跳转到对应 tabBar 页面
+  const pages = [
+    '/pages/index/index',
+    '/pages/index/therapy',
+    '/pages/index/order',
+    '/pages/index/merchant',
+    '/pages/index/my'
+  ];
+  uni.switchTab({ url: pages[index] });
+};
+</script>
+
+<style scoped>
+.page {
+  min-height: 100vh;
+  padding-bottom: 100rpx; /* 防止内容被遮挡 */
+  background-color: #f8f8f8;
+  padding: 20rpx;
+}
+
+.content {
+  font-size: 32rpx;
+  color: #333;
+}
+</style>

+ 52 - 0
pages/index/order.uvue

@@ -0,0 +1,52 @@
+<template>
+  <view class="page">
+    <view class="content">当前页面:{{ currentTabName }}</view>
+
+    <!-- 自定义底部导航 -->
+    <CustomBottomNav 
+      :current-index="currentTab" 
+      @change="onTabChange" 
+    />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue';
+import CustomBottomNav from '@/components/CustomBottomNav.uvue';
+
+// 当前选中索引
+const currentTab = ref(2);
+
+// 根据索引获取名称(用于演示)
+const tabNames = ['小丁', '理疗', '预约', '商户', '我的'];
+const currentTabName = computed(() => tabNames[currentTab.value]);
+
+// 切换 Tab
+const onTabChange = (index: number) => {
+  currentTab.value = index;
+
+  // 可选:跳转到对应 tabBar 页面
+  const pages = [
+    '/pages/index/index',
+    '/pages/index/therapy',
+    '/pages/index/order',
+    '/pages/index/merchant',
+    '/pages/index/my'
+  ];
+  uni.switchTab({ url: pages[index] });
+};
+</script>
+
+<style scoped>
+.page {
+  min-height: 100vh;
+  padding-bottom: 100rpx; /* 防止内容被遮挡 */
+  background-color: #f8f8f8;
+  padding: 20rpx;
+}
+
+.content {
+  font-size: 32rpx;
+  color: #333;
+}
+</style>

+ 52 - 0
pages/index/therapy.uvue

@@ -0,0 +1,52 @@
+<template>
+  <view class="page">
+    <view class="content">当前页面:{{ currentTabName }}</view>
+
+    <!-- 自定义底部导航 -->
+    <CustomBottomNav 
+      :current-index="currentTab" 
+      @change="onTabChange" 
+    />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue';
+import CustomBottomNav from '@/components/CustomBottomNav.uvue';
+
+// 当前选中索引
+const currentTab = ref(1);
+
+// 根据索引获取名称(用于演示)
+const tabNames = ['小丁', '理疗', '预约', '商户', '我的'];
+const currentTabName = computed(() => tabNames[currentTab.value]);
+
+// 切换 Tab
+const onTabChange = (index: number) => {
+  currentTab.value = index;
+
+  // 可选:跳转到对应 tabBar 页面
+  const pages = [
+    '/pages/index/index',
+    '/pages/index/therapy',
+    '/pages/index/order',
+    '/pages/index/merchant',
+    '/pages/index/my'
+  ];
+  uni.switchTab({ url: pages[index] });
+};
+</script>
+
+<style scoped>
+.page {
+  min-height: 100vh;
+  padding-bottom: 100rpx; /* 防止内容被遮挡 */
+  background-color: #f8f8f8;
+  padding: 20rpx;
+}
+
+.content {
+  font-size: 32rpx;
+  color: #333;
+}
+</style>

BIN
static/logo.png


+ 76 - 0
uni.scss

@@ -0,0 +1,76 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:12px;
+$uni-font-size-base:14px;
+$uni-font-size-lg:16px;
+
+/* 图片尺寸 */
+$uni-img-size-sm:20px;
+$uni-img-size-base:26px;
+$uni-img-size-lg:40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:20px;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:26px;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:15px;

+ 8 - 0
unpackage/dist/cache/.vite/deps/_metadata.json

@@ -0,0 +1,8 @@
+{
+  "hash": "1140b430",
+  "configHash": "6ecf035f",
+  "lockfileHash": "e3b0c442",
+  "browserHash": "3e2c3012",
+  "optimized": {},
+  "chunks": {}
+}

+ 3 - 0
unpackage/dist/cache/.vite/deps/package.json

@@ -0,0 +1,3 @@
+{
+  "type": "module"
+}