diff --git a/App.vue b/App.vue index 05655d3..b031520 100644 --- a/App.vue +++ b/App.vue @@ -1,22 +1,17 @@ +@import './common/main.css'; +// @import './common/layouts.less'; diff --git a/common/layouts-example.less b/common/layouts-example.less deleted file mode 100644 index a062d97..0000000 --- a/common/layouts-example.less +++ /dev/null @@ -1,108 +0,0 @@ -// layouts.less 使用示例 -// 这个文件展示了如何在页面中使用 common/layouts.less 中的布局方法 - -// 示例1: 使用Flex布局 -.example-flex { - .flex-between; // 使用两端对齐布局 - padding: 20px; - background-color: #f5f5f5; - - .item { - .flex-center; // 使用居中布局 - width: 100px; - height: 100px; - background-color: #007aff; - color: white; - border-radius: 8px; - } -} - -// 示例2: 使用Grid布局 -.example-grid { - .grid-responsive(4, 16px); // 使用响应式网格,4列,间距16px - padding: 20px; - - .item { - height: 120px; - background-color: #ff9500; - border-radius: 8px; - - &:nth-child(1) { - .grid-col(2); // 占据2列 - } - } -} - -// 示例3: 使用卡片布局 -.example-card { - max-width: 400px; - margin: 20px auto; - - .card(); // 使用基础卡片样式 - - .card-header { - font-size: 18px; - font-weight: bold; - } - - .card-body { - .flex-column; - gap: 16px; - } - - .card-footer { - .flex-between; - } -} - -// 示例4: 使用响应式布局 -.example-responsive { - display: flex; - gap: 20px; - padding: 20px; - - .desktop-only { - .hidden-sm; // 在小屏幕上隐藏 - width: 200px; - height: 200px; - background-color: #4cd964; - } - - .mobile-only { - .visible-sm; // 只在小屏幕上显示 - width: 100%; - height: 100px; - background-color: #ff3b30; - } -} - -// 示例5: 使用间距工具类 -.example-spacing { - .m-4; // margin: 16px - .p-6; // padding: 24px - background-color: #e9e9eb; - - .child { - .mt-3; // margin-top: 12px - .mb-3; // margin-bottom: 12px - .px-4; // padding-left: 16px; padding-right: 16px - background-color: #ffffff; - } -} - -// 示例6: 使用页面布局 -.example-page { - .page-with-header-footer; - - .page-header { - .navbar-top; - } - - .page-content { - .container-responsive; - } - - .page-footer { - .navbar-bottom; - } -} \ No newline at end of file diff --git a/common/layouts.less b/common/layouts.less deleted file mode 100644 index fa63b61..0000000 --- a/common/layouts.less +++ /dev/null @@ -1,446 +0,0 @@ -// 布局专用LESS文件 -// 包含常用的布局混合宏和样式 - -// ------------------------------ -// 容器布局 -// ------------------------------ - -// 全屏容器 -.full-screen { - width: 100%; - height: 100vh; -} - -// 固定宽度容器 -.container-fixed(@width: 1200px) { - width: @width; - margin: 0 auto; - padding: 0 20px; -} - -// 响应式容器 -.container-responsive { - width: 100%; - margin: 0 auto; - padding: 0 20px; - max-width: 1200px; -} - -// ------------------------------ -// Flex布局混合宏 -// ------------------------------ - -// 基础Flex布局 -.flex(@direction: row; @wrap: nowrap; @justify: flex-start; @align: stretch) { - display: flex; - flex-direction: @direction; - flex-wrap: @wrap; - justify-content: @justify; - align-items: @align; -} - -// 居中布局 -.flex-center { - .flex(row, nowrap, center, center); -} - -// 两端对齐 -.flex-between { - .flex(row, nowrap, space-between, center); -} - -// 顶部对齐 -.flex-start { - .flex(row, nowrap, flex-start, flex-start); -} - -// 底部对齐 -.flex-end { - .flex(row, nowrap, flex-end, flex-end); -} - -// 垂直居中 -.flex-middle { - .flex(row, nowrap, flex-start, center); -} - -// 垂直布局 -.flex-column { - .flex(column, nowrap, flex-start, stretch); -} - -// 垂直居中布局 -.flex-column-center { - .flex(column, nowrap, center, center); -} - -// 垂直两端对齐 -.flex-column-between { - .flex(column, nowrap, space-between, stretch); -} - -// ------------------------------ -// 网格布局 -// ------------------------------ - -// 基础网格容器 -.grid(@columns: 12; @gap: 20px) { - display: grid; - grid-template-columns: repeat(@columns, 1fr); - grid-gap: @gap; - gap: @gap; -} - -// 响应式网格 -.grid-responsive(@columns: 12; @gap: 20px) { - .grid(@columns, @gap); - - @media (max-width: 768px) { - grid-template-columns: repeat(6, 1fr); - } - - @media (max-width: 480px) { - grid-template-columns: repeat(3, 1fr); - } -} - -// 网格列宽 -.grid-col(@span: 1) { - grid-column: span @span; -} - -// 网格行高 -.grid-row(@span: 1) { - grid-row: span @span; -} - -// ------------------------------ -// 定位布局 -// ------------------------------ - -// 绝对定位 -.position-absolute(@top: auto; @right: auto; @bottom: auto; @left: auto) { - position: absolute; - top: @top; - right: @right; - bottom: @bottom; - left: @left; -} - -// 固定定位 -.position-fixed(@top: auto; @right: auto; @bottom: auto; @left: auto) { - position: fixed; - top: @top; - right: @right; - bottom: @bottom; - left: @left; -} - -// 粘性定位 -.position-sticky(@top: 0; @z-index: 10) { - position: sticky; - top: @top; - z-index: @z-index; -} - -// 居中定位(基于父容器) -.position-center { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); -} - -// 水平居中定位 -.position-center-x { - position: absolute; - left: 50%; - transform: translateX(-50%); -} - -// 垂直居中定位 -.position-center-y { - position: absolute; - top: 50%; - transform: translateY(-50%); -} - -// ------------------------------ -// 间距布局 -// ------------------------------ - -// 外边距 -.margin(@top: 0; @right: @top; @bottom: @top; @left: @right) { - margin: @top @right @bottom @left; -} - -// 内边距 -.padding(@top: 0; @right: @top; @bottom: @top; @left: @right) { - padding: @top @right @bottom @left; -} - -// 间距工具类(基于4px网格系统) -.spacing-utilities(@prefix: m; @property: margin) { - .loop(@i) when (@i <= 12) { - .@{prefix}-@{i} { - @{property}: @i * 4px; - } - - .@{prefix}t-@{i} { - @{property}-top: @i * 4px; - } - - .@{prefix}r-@{i} { - @{property}-right: @i * 4px; - } - - .@{prefix}b-@{i} { - @{property}-bottom: @i * 4px; - } - - .@{prefix}l-@{i} { - @{property}-left: @i * 4px; - } - - .loop(@i + 1); - } - - .loop(0); -} - -// 生成外边距工具类 -.spacing-utilities(m, margin); - -// 生成内边距工具类 -.spacing-utilities(p, padding); - -// ------------------------------ -// 卡片布局 -// ------------------------------ - -// 基础卡片 -.card(@radius: 8px; @shadow: 0 2px 8px rgba(0, 0, 0, 0.1); @bg: #fff) { - background-color: @bg; - border-radius: @radius; - box-shadow: @shadow; - overflow: hidden; -} - -// 带边框的卡片 -.card-bordered(@radius: 8px; @border-color: #e5e5e5; @bg: #fff) { - .card(@radius, none, @bg); - border: 1px solid @border-color; -} - -// 卡片头部 -.card-header { - padding: 16px 20px; - border-bottom: 1px solid #e5e5e5; -} - -// 卡片主体 -.card-body { - padding: 20px; -} - -// 卡片底部 -.card-footer { - padding: 16px 20px; - border-top: 1px solid #e5e5e5; - background-color: #fafafa; -} - -// ------------------------------ -// 导航栏布局 -// ------------------------------ - -// 基础导航栏 -.navbar(@height: 60px; @bg-color: #fff; @text-color: #333) { - height: @height; - background-color: @bg-color; - color: @text-color; - display: flex; - align-items: center; - padding: 0 20px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); -} - -// 顶部导航栏 -.navbar-top { - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 1000; - .navbar(); -} - -// 底部导航栏 -.navbar-bottom { - position: fixed; - bottom: 0; - left: 0; - right: 0; - z-index: 1000; - .navbar(); - border-top: 1px solid #e5e5e5; -} - -// ------------------------------ -// 页面布局 -// ------------------------------ - -// 基础页面布局 -.page-layout { - min-height: 100vh; - display: flex; - flex-direction: column; -} - -// 带头部和底部的页面布局 -.page-with-header-footer { - .page-layout(); - - .page-header { - flex-shrink: 0; - } - - .page-content { - flex: 1; - padding: 20px; - overflow-y: auto; - } - - .page-footer { - flex-shrink: 0; - } -} - -// ------------------------------ -// 响应式布局 -// ------------------------------ - -// 断点定义 -@breakpoint-sm: 480px; -@breakpoint-md: 768px; -@breakpoint-lg: 1024px; -@breakpoint-xl: 1200px; - -// 媒体查询混合宏 -.media-sm(@rules) { - @media (max-width: @breakpoint-sm) { - @rules(); - } -} - -.media-md(@rules) { - @media (max-width: @breakpoint-md) { - @rules(); - } -} - -.media-lg(@rules) { - @media (max-width: @breakpoint-lg) { - @rules(); - } -} - -.media-xl(@rules) { - @media (max-width: @breakpoint-xl) { - @rules(); - } -} - -// 响应式显示/隐藏 -.hidden-sm { - .media-sm({ - display: none; - }); -} - -.visible-sm { - display: none; - .media-sm({ - display: block; - }); -} - -.hidden-md { - .media-md({ - display: none; - }); -} - -.visible-md { - display: none; - .media-md({ - display: block; - }); -} - -// ------------------------------ -// 其他布局工具 -// ------------------------------ - -// 清除浮动 -.clearfix { - &::after { - content: ''; - display: table; - clear: both; - } -} - -// 相对定位 -.relative { - position: relative; -} - -// 绝对定位 -.absolute { - position: absolute; -} - -// 固定定位 -.fixed { - position: fixed; -} - -// 粘性定位 -.sticky { - position: sticky; -} - -// 隐藏溢出 -.overflow-hidden { - overflow: hidden; -} - -// 自动溢出 -.overflow-auto { - overflow: auto; -} - -// 水平滚动 -.overflow-x-auto { - overflow-x: auto; - overflow-y: hidden; -} - -// 垂直滚动 -.overflow-y-auto { - overflow-y: auto; - overflow-x: hidden; -} - -// 全屏高度 -.full-height { - height: 100%; - min-height: 100vh; -} - -// 全屏宽度 -.full-width { - width: 100%; - max-width: 100%; -} diff --git a/common/main.css b/common/main.css index 95bbca7..0e53fce 100644 --- a/common/main.css +++ b/common/main.css @@ -2,276 +2,408 @@ /* 重置样式 */ * { - margin: 0; - padding: 0; - box-sizing: border-box; - /* color: var(--text-color); */ + margin: 0; + padding: 0; + box-sizing: border-box; + /* color: var(--text-color); */ } /* 基础样式 */ body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; - font-size: 14px; - line-height: 1.5; - color: #333; - background-color: #f5f5f5; + /* font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Helvetica Neue", Arial, sans-serif; */ + font-size: 14px; + line-height: 1.5; + color: var(--text-color); + background-color: var(--page-bg-color); +} + +.w100 { + width: 100% +} + +.h100 { + height: 100%; } /* 常用颜色变量 */ :root { - --text-color: #1a1a1a; - --primary-color: #007aff; - --success-color: #4cd964; - --warning-color: #ff9500; - --error-color: #ff3b30; - --text-primary: #333; - --text-secondary: #666; - --text-tertiary: #999; - --bg-primary: #fff; - --bg-secondary: #f5f5f5; - --border-color: #e5e5e5; + --text-color: #1a1a1a; + --primary-color: #007aff; + --success-color: #4cd964; + --warning-color: #ff9500; + --error-color: #ff3b30; + --text-primary: #333; + --text-secondary: #969696; + --text-tertiary: #999; + --bg-primary: #ffffff; + --bg-secondary: #f5f5f5; + --border-color: #D8D8D8; + --page-bg-color: #f0f3f8; + --footer-text-color: #CBCED3; } /* 文本样式 */ .text-center { - text-align: center; + text-align: center; } .text-left { - text-align: left; + text-align: left; } .text-right { - text-align: right; + text-align: right; } .text-primary { - color: var(--primary-color); + color: var(--primary-color); } .text-success { - color: var(--success-color); + color: var(--success-color); } .text-warning { - color: var(--warning-color); + color: var(--warning-color); } .text-error { - color: var(--error-color); + color: var(--error-color); } .text-sm { - font-size: 12px; + font-size: 12px; } .text-lg { - font-size: 16px; + font-size: 16px; } .text-xl { - font-size: 18px; + font-size: 18px; } /* 间距工具类 */ -.m-0 { margin: 0; } -.m-1 { margin: 4px; } -.m-2 { margin: 8px; } -.m-3 { margin: 16px; } -.m-4 { margin: 24px; } +.m-0 { + margin: 0; +} -.mt-0 { margin-top: 0; } -.mt-1 { margin-top: 4px; } -.mt-2 { margin-top: 8px; } -.mt-3 { margin-top: 16px; } -.mt-4 { margin-top: 24px; } +.m-1 { + margin: 4px; +} -.mb-0 { margin-bottom: 0; } -.mb-1 { margin-bottom: 4px; } -.mb-2 { margin-bottom: 8px; } -.mb-3 { margin-bottom: 16px; } -.mb-4 { margin-bottom: 24px; } +.m-2 { + margin: 8px; +} -.ml-0 { margin-left: 0; } -.ml-1 { margin-left: 4px; } -.ml-2 { margin-left: 8px; } -.ml-3 { margin-left: 16px; } -.ml-4 { margin-left: 24px; } +.m-3 { + margin: 16px; +} -.mr-0 { margin-right: 0; } -.mr-1 { margin-right: 4px; } -.mr-2 { margin-right: 8px; } -.mr-3 { margin-right: 16px; } -.mr-4 { margin-right: 24px; } +.m-4 { + margin: 24px; +} -.p-0 { padding: 0; } -.p-1 { padding: 4px; } -.p-2 { padding: 8px; } -.p-3 { padding: 16px; } -.p-4 { padding: 24px; } +.mt-0 { + margin-top: 0; +} -.pt-0 { padding-top: 0; } -.pt-1 { padding-top: 4px; } -.pt-2 { padding-top: 8px; } -.pt-3 { padding-top: 16px; } -.pt-4 { padding-top: 24px; } +.mt-1 { + margin-top: 4px; +} -.pb-0 { padding-bottom: 0; } -.pb-1 { padding-bottom: 4px; } -.pb-2 { padding-bottom: 8px; } -.pb-3 { padding-bottom: 16px; } -.pb-4 { padding-bottom: 24px; } +.mt-2 { + margin-top: 8px; +} -.pl-0 { padding-left: 0; } -.pl-1 { padding-left: 4px; } -.pl-2 { padding-left: 8px; } -.pl-3 { padding-left: 16px; } -.pl-4 { padding-left: 24px; } +.mt-3 { + margin-top: 16px; +} -.pr-0 { padding-right: 0; } -.pr-1 { padding-right: 4px; } -.pr-2 { padding-right: 8px; } -.pr-3 { padding-right: 16px; } -.pr-4 { padding-right: 24px; } +.mt-4 { + margin-top: 24px; +} + +.mb-0 { + margin-bottom: 0; +} + +.mb-1 { + margin-bottom: 4px; +} + +.mb-2 { + margin-bottom: 8px; +} + +.mb-3 { + margin-bottom: 16px; +} + +.mb-4 { + margin-bottom: 24px; +} + +.ml-0 { + margin-left: 0; +} + +.ml-1 { + margin-left: 4px; +} + +.ml-2 { + margin-left: 8px; +} + +.ml-3 { + margin-left: 16px; +} + +.ml-4 { + margin-left: 24px; +} + +.mr-0 { + margin-right: 0; +} + +.mr-1 { + margin-right: 4px; +} + +.mr-2 { + margin-right: 8px; +} + +.mr-3 { + margin-right: 16px; +} + +.mr-4 { + margin-right: 24px; +} + +.p-0 { + padding: 0; +} + +.p-1 { + padding: 4px; +} + +.p-2 { + padding: 8px; +} + +.p-3 { + padding: 16px; +} + +.p-4 { + padding: 24px; +} + +.pt-0 { + padding-top: 0; +} + +.pt-1 { + padding-top: 4px; +} + +.pt-2 { + padding-top: 8px; +} + +.pt-3 { + padding-top: 16px; +} + +.pt-4 { + padding-top: 24px; +} + +.pb-0 { + padding-bottom: 0; +} + +.pb-1 { + padding-bottom: 4px; +} + +.pb-2 { + padding-bottom: 8px; +} + +.pb-3 { + padding-bottom: 16px; +} + +.pb-4 { + padding-bottom: 24px; +} + +.pl-0 { + padding-left: 0; +} + +.pl-1 { + padding-left: 4px; +} + +.pl-2 { + padding-left: 8px; +} + +.pl-3 { + padding-left: 16px; +} + +.pl-4 { + padding-left: 24px; +} + +.pr-0 { + padding-right: 0; +} + +.pr-1 { + padding-right: 4px; +} + +.pr-2 { + padding-right: 8px; +} + +.pr-3 { + padding-right: 16px; +} + +.pr-4 { + padding-right: 24px; +} /* 布局工具类 */ .flex { - display: flex; + display: flex; } .flex-column { - flex-direction: column; + flex-direction: column; } .flex-center { - display: flex; - align-items: center; - justify-content: center; + display: flex; + align-items: center; + justify-content: center; } .flex-between { - display: flex; - align-items: center; - justify-content: space-between; + display: flex; + align-items: center; + justify-content: space-between; } .flex-align-center { - display: flex; - align-items: center; + display: flex; + align-items: center; } .flex-justify-center { - display: flex; - justify-content: center; + display: flex; + justify-content: center; } .flex-wrap { - flex-wrap: wrap; + flex-wrap: wrap; +} + +.flex-1 { + flex: 1; } /* 边框样式 */ -.border { - border: 1px solid var(--border-color); -} - -.border-top { - border-top: 1px solid var(--border-color); -} - -.border-bottom { - border-bottom: 1px solid var(--border-color); -} - -.border-left { - border-left: 1px solid var(--border-color); -} - -.border-right { - border-right: 1px solid var(--border-color); -} - -.rounded { - border-radius: 4px; -} - -.rounded-lg { - border-radius: 8px; -} +/* 圆角 */ .rounded-full { - border-radius: 50%; + border-radius: 50%; } /* 背景色 */ .bg-primary { - background-color: var(--bg-primary); + background-color: var(--bg-primary); } .bg-secondary { - background-color: var(--bg-secondary); + background-color: var(--bg-secondary); } .bg-primary-color { - background-color: var(--primary-color); + background-color: var(--primary-color); } .bg-success-color { - background-color: var(--success-color); + background-color: var(--success-color); } .bg-warning-color { - background-color: var(--warning-color); + background-color: var(--warning-color); } .bg-error-color { - background-color: var(--error-color); + background-color: var(--error-color); } -/* 尺寸工具类 */ -.w-full { - width: 100%; -} - -.h-full { - height: 100%; -} - -.w-auto { - width: auto; -} - -.h-auto { - height: auto; -} /* 隐藏元素 */ .hidden { - display: none; + display: none; } /* 显示元素 */ .block { - display: block; -} - -/* 溢出处理 */ -.overflow-hidden { - overflow: hidden; -} - -.overflow-auto { - overflow: auto; + display: block; } /* 文本截断 */ .text-ellipsis { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } -/* 透明度 */ -.opacity-100 { opacity: 1; } -.opacity-75 { opacity: 0.75; } -.opacity-50 { opacity: 0.5; } -.opacity-25 { opacity: 0.25; } + +/* 字体 */ + +.font-w500 { + font-weight: 500; +} + +@font-face { + font-family: "alipayNumber"; + src: url("/static/font/AlipayNumber.ttf") format("truetype"); +} + +@font-face { + font-family: "wxNumberRegular"; + src: url("/static/font/WeChatSansStd-Regular.otf"); +} + +@font-face { + font-family: "wxNumberMedium"; + src: url("/static/font/WeChatSansStd-Medium.otf"); +} + +.alipay-font { + font-family: "alipayNumber"; +} + +.wx-font-regular { + font-family: "wxNumberRegular"; +} + +.wx-font-medium { + font-family: "wxNumberMedium"; +} \ No newline at end of file diff --git a/components/balance-list/balance-list.vue b/components/balance-list/balance-list.vue new file mode 100644 index 0000000..804a907 --- /dev/null +++ b/components/balance-list/balance-list.vue @@ -0,0 +1,144 @@ + + + + + + + \ No newline at end of file diff --git a/components/nav-bar/nav-bar.vue b/components/nav-bar/nav-bar.vue index 2ed5be3..ea066cf 100644 --- a/components/nav-bar/nav-bar.vue +++ b/components/nav-bar/nav-bar.vue @@ -1,71 +1,207 @@ \ No newline at end of file diff --git a/components/popup/popup.vue b/components/popup/popup.vue new file mode 100644 index 0000000..be06334 --- /dev/null +++ b/components/popup/popup.vue @@ -0,0 +1,96 @@ + + + + + \ No newline at end of file diff --git a/pages.json b/pages.json index 498f1b5..5db405a 100644 --- a/pages.json +++ b/pages.json @@ -1,26 +1,45 @@ { - "pages": [ - //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages - { - "path": "pages/balance/index", - "style": { - "navigationBarTitleText": "余额页面", - "navigationStyle": "custom" - } - }, - { - "path": "pages/index/index", - "style": { - "navigationBarTitleText": "uni-app", - "navigationStyle": "custom" - } - } - ], - "globalStyle": { - "navigationBarTextStyle": "black", - "navigationBarTitleText": "uni-app", - "navigationBarBackgroundColor": "#F8F8F8", - "backgroundColor": "#F8F8F8" - }, - "uniIdRouter": {} -} + "pages": [ + //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/balance/index", + "style": { + "navigationBarTitleText": "余额页面", + "navigationStyle": "custom" + } + }, + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "uni-app", + "navigationStyle": "custom" + } + }, + { + "path": "pages/bill/bill-list/bill-list", + "style": { + "navigationBarTitleText": "账单列表页面", + "navigationStyle": "custom" + } + }, + { + "path": "pages/bill/add-bill/add-bill", + "style": { + "navigationBarTitleText": "新增账单", + "navigationStyle": "custom" + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8", + "androidNavigationBar": { + "navigationBarBackgroundColor": "#00000000", // 完全透明 + "navigationBarTextStyle": "white", // 虚拟按键图标颜色 + "backgroundColor": "#00000000" // 背景透明 + } + }, + "uniIdRouter": {} +} \ No newline at end of file diff --git a/pages/balance/index.nvue b/pages/balance/index.nvue deleted file mode 100644 index 09d7681..0000000 --- a/pages/balance/index.nvue +++ /dev/null @@ -1,316 +0,0 @@ - - - - - \ No newline at end of file diff --git a/pages/balance/index.vue b/pages/balance/index.vue new file mode 100644 index 0000000..361acf2 --- /dev/null +++ b/pages/balance/index.vue @@ -0,0 +1,529 @@ + + + + + + + \ No newline at end of file diff --git a/pages/bill/add-bill/add-bill.vue b/pages/bill/add-bill/add-bill.vue new file mode 100644 index 0000000..193e5f9 --- /dev/null +++ b/pages/bill/add-bill/add-bill.vue @@ -0,0 +1,48 @@ + + + + + + \ No newline at end of file diff --git a/pages/bill/bill-list/bill-list.vue b/pages/bill/bill-list/bill-list.vue new file mode 100644 index 0000000..986ec7d --- /dev/null +++ b/pages/bill/bill-list/bill-list.vue @@ -0,0 +1,704 @@ + + + + + + \ No newline at end of file diff --git a/pages/index/index.vue b/pages/index/index.vue index 0c1169b..3652aa2 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -1,321 +1,3 @@ - - - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/static/font/AlipayNumber.ttf b/static/font/AlipayNumber.ttf new file mode 100644 index 0000000..3c04d7d Binary files /dev/null and b/static/font/AlipayNumber.ttf differ diff --git a/static/font/WeChatSansStd-Medium.otf b/static/font/WeChatSansStd-Medium.otf new file mode 100644 index 0000000..6819caf Binary files /dev/null and b/static/font/WeChatSansStd-Medium.otf differ diff --git a/static/font/WeChatSansStd-Regular.otf b/static/font/WeChatSansStd-Regular.otf new file mode 100644 index 0000000..57fba55 Binary files /dev/null and b/static/font/WeChatSansStd-Regular.otf differ diff --git a/static/image/bill/bill-list/current-month-bill-bg.png b/static/image/bill/bill-list/current-month-bill-bg.png new file mode 100644 index 0000000..47d03bd Binary files /dev/null and b/static/image/bill/bill-list/current-month-bill-bg.png differ diff --git a/static/image/bill/bill-list/down-black.png b/static/image/bill/bill-list/down-black.png new file mode 100644 index 0000000..538f3d6 Binary files /dev/null and b/static/image/bill/bill-list/down-black.png differ diff --git a/static/image/bill/bill-list/search-black.png b/static/image/bill/bill-list/search-black.png new file mode 100644 index 0000000..b65c263 Binary files /dev/null and b/static/image/bill/bill-list/search-black.png differ diff --git a/static/image/common/right-black.png b/static/image/common/right-black.png new file mode 100644 index 0000000..4a297e9 Binary files /dev/null and b/static/image/common/right-black.png differ diff --git a/static/image/common/right-grey.png b/static/image/common/right-grey.png new file mode 100644 index 0000000..78133fe Binary files /dev/null and b/static/image/common/right-grey.png differ diff --git a/static/image/nav-bar/back-black.png b/static/image/nav-bar/back-black.png new file mode 100644 index 0000000..44924bd Binary files /dev/null and b/static/image/nav-bar/back-black.png differ diff --git a/static/image/nav-bar/more-black.png b/static/image/nav-bar/more-black.png new file mode 100644 index 0000000..6f27713 Binary files /dev/null and b/static/image/nav-bar/more-black.png differ diff --git a/store/index.js b/store/index.js index de96bb9..1339241 100644 --- a/store/index.js +++ b/store/index.js @@ -7,27 +7,27 @@ import { storage } from '../utils/storage'; export const store = reactive({ // 用户信息 userInfo: storage.get('userInfo') || null, - + // 应用设置 settings: storage.get('settings') || { theme: 'light', language: 'zh-CN', notifications: true }, - + // 系统信息 systemInfo: { statusBarHeight: 0, windowHeight: 0, windowWidth: 0 }, - + // 示例数据:待办事项 todos: storage.get('todos') || [], - + // 示例数据:商品列表 products: storage.get('products') || [], - + }); @@ -59,7 +59,7 @@ export const useStore = () => { return newTodo; }; - const updateTodo = (id, updates) => { + const updateTodo = (id, updates) => { const index = store.todos.findIndex(todo => todo.id === id); if (index !== -1) { store.todos[index] = { ...store.todos[index], ...updates }; diff --git a/utils/common.js b/utils/common.js index 2b0eeba..ce91d9c 100644 --- a/utils/common.js +++ b/utils/common.js @@ -12,18 +12,18 @@ export const dateUtil = { */ format(date, format = 'YYYY-MM-DD HH:mm:ss') { if (!date) return ''; - + if (typeof date === 'string' || typeof date === 'number') { date = new Date(date); } - + const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); - + return format .replace('YYYY', year) .replace('MM', month) @@ -32,7 +32,7 @@ export const dateUtil = { .replace('mm', minutes) .replace('ss', seconds); }, - + /** * 获取当前日期 * @param {string} format - 格式化字符串 @@ -41,7 +41,7 @@ export const dateUtil = { now(format = 'YYYY-MM-DD HH:mm:ss') { return this.format(new Date(), format); }, - + /** * 获取相对时间 * @param {Date|string|number} date - 日期对象或时间戳 @@ -49,23 +49,23 @@ export const dateUtil = { */ relative(date) { if (!date) return ''; - + if (typeof date === 'string' || typeof date === 'number') { date = new Date(date); } - + const now = new Date(); const diff = now - date; const seconds = Math.floor(diff / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); - + if (seconds < 60) return '刚刚'; if (minutes < 60) return `${minutes}分钟前`; if (hours < 24) return `${hours}小时前`; if (days < 30) return `${days}天前`; - + return this.format(date, 'YYYY-MM-DD'); } }; @@ -81,13 +81,13 @@ export const numberUtil = { */ format(num) { if (num === null || num === undefined) return '0'; - + const number = typeof num === 'string' ? parseFloat(num) : num; if (isNaN(number)) return '0'; - + return number.toLocaleString(); }, - + /** * 格式化金额 * @param {number|string} amount - 金额 @@ -96,13 +96,13 @@ export const numberUtil = { */ formatMoney(amount, decimals = 2) { if (amount === null || amount === undefined) return '0.00'; - + const number = typeof amount === 'string' ? parseFloat(amount) : amount; if (isNaN(number)) return '0.00'; - + return number.toFixed(decimals); }, - + /** * 随机数生成 * @param {number} min - 最小值 @@ -127,22 +127,22 @@ export const stringUtil = { */ truncate(str, length, suffix = '...') { if (!str || str.length <= length) return str; - + return str.substring(0, length) + suffix; }, - + /** * 生成唯一ID * @returns {string} 唯一ID */ uuid() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = Math.random() * 16 | 0; const v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); }, - + /** * 手机号脱敏 * @param {string} phone - 手机号 @@ -150,10 +150,10 @@ export const stringUtil = { */ maskPhone(phone) { if (!phone || phone.length !== 11) return phone; - + return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'); }, - + /** * 身份证号脱敏 * @param {string} idCard - 身份证号 @@ -161,10 +161,10 @@ export const stringUtil = { */ maskIdCard(idCard) { if (!idCard) return idCard; - + const length = idCard.length; if (length < 8) return idCard; - + return idCard.substring(0, 4) + '*'.repeat(length - 8) + idCard.substring(length - 4); } }; @@ -185,7 +185,7 @@ export const deviceUtil = { }); }); }, - + /** * 获取状态栏高度 * @returns {Promise} 状态栏高度 @@ -199,7 +199,7 @@ export const deviceUtil = { return 0; } }, - + /** * 判断是否为iOS设备 * @returns {Promise} 是否为iOS设备 @@ -213,7 +213,7 @@ export const deviceUtil = { return false; } }, - + /** * 判断是否为Android设备 * @returns {Promise} 是否为Android设备 @@ -227,35 +227,7 @@ export const deviceUtil = { return false; } }, - - /** - * 获取屏幕宽度 - * @returns {Promise} 屏幕宽度(px) - */ - async getScreenWidth() { - try { - const systemInfo = await this.getSystemInfo(); - return systemInfo.screenWidth || 0; - } catch (error) { - console.error('获取屏幕宽度失败:', error); - return 0; - } - }, - - /** - * 获取屏幕高度 - * @returns {Promise} 屏幕高度(px) - */ - async getScreenHeight() { - try { - const systemInfo = await this.getSystemInfo(); - return systemInfo.screenHeight || 0; - } catch (error) { - console.error('获取屏幕高度失败:', error); - return 0; - } - }, - + /** * 获取窗口宽度 * @returns {Promise} 窗口宽度(px) @@ -269,7 +241,7 @@ export const deviceUtil = { return 0; } }, - + /** * 获取窗口高度 * @returns {Promise} 窗口高度(px) @@ -285,37 +257,6 @@ export const deviceUtil = { } }; -/** - * 网络请求相关方法 - */ -export const networkUtil = { - /** - * 检查网络状态 - * @returns {Promise} 网络状态对象 - */ - checkNetwork() { - return new Promise((resolve, reject) => { - uni.getNetworkType({ - success: resolve, - fail: reject - }); - }); - }, - - /** - * 判断是否有网络连接 - * @returns {Promise} 是否有网络连接 - */ - async isConnected() { - try { - const networkType = await this.checkNetwork(); - return networkType.networkType !== 'none'; - } catch (error) { - console.error('检查网络状态失败:', error); - return false; - } - } -}; /** * UI相关方法 @@ -333,7 +274,7 @@ export const uiUtil = { mask }); }, - + /** * 隐藏加载提示 * @returns {void} @@ -341,21 +282,7 @@ export const uiUtil = { hideLoading() { uni.hideLoading(); }, - - /** - * 显示成功提示 - * @param {string} title - 提示文本 - * @param {number} duration - 显示时长 - * @returns {void} - */ - showSuccess(title, duration = 1500) { - uni.showToast({ - title, - icon: 'success', - duration - }); - }, - + /** * 显示错误提示 * @param {string} title - 提示文本 @@ -369,7 +296,7 @@ export const uiUtil = { duration }); }, - + /** * 显示警告提示 * @param {string} title - 提示文本 @@ -397,65 +324,55 @@ export const uiUtil = { * 其他工具方法 */ export const util = { - /** - * 深拷贝对象 - * @param {Object} obj - 原始对象 - * @returns {Object} 拷贝后的对象 - */ - deepClone(obj) { - if (obj === null || typeof obj !== 'object') return obj; - - if (obj instanceof Date) return new Date(obj.getTime()); - if (obj instanceof Array) return obj.map(item => this.deepClone(item)); - - const clonedObj = {}; - for (const key in obj) { - if (obj.hasOwnProperty(key)) { - clonedObj[key] = this.deepClone(obj[key]); + setAndroidSystemBarColor(backgroundColor) { + if (deviceUtil.isAndroid()) { + try { + // #ifndef APP-IOS + if (plus.os.name === 'Android') { + console.log("1212333"); + let color = plus.android.newObject("android.graphics.Color"); + let activity = plus.android.runtimeMainActivity(); + let colorInt = plus.android.invoke(color, "parseColor", backgroundColor); + let window = plus.android.invoke(activity, "getWindow"); + plus.android.invoke(window, "setNavigationBarColor", colorInt); + uni.setNavigationBarColor({ + animation: { // 动画效果 + duration: 100, + timingFunc: 'easeIn' + } + }) + console.log("状态栏设置完毕!"); + setTimeout(function () { + uni.setNavigationBarColor({ + backgroundColor: backgroundColor, + animation: { // 动画效果 + duration: 100, + timingFunc: 'easeIn' + } + }) + }, 200); + } + // #endif + } catch (err) { + console.log("状态栏修改失败", err); + uni.setNavigationBarColor({ + animation: { // 动画效果 + duration: 100, + timingFunc: 'easeIn' + } + }) } } - - return clonedObj; }, - + /** - * 防抖函数 - * @param {Function} func - 要执行的函数 - * @param {number} wait - 等待时间 - * @returns {Function} 防抖后的函数 + * 页面跳转 + * @param {*} url */ - debounce(func, wait = 300) { - let timeout; - return function(...args) { - clearTimeout(timeout); - timeout = setTimeout(() => func.apply(this, args), wait); - }; - }, - - /** - * 节流函数 - * @param {Function} func - 要执行的函数 - * @param {number} limit - 限制时间 - * @returns {Function} 节流后的函数 - */ - throttle(func, limit = 300) { - let inThrottle; - return function(...args) { - if (!inThrottle) { - func.apply(this, args); - inThrottle = true; - setTimeout(() => inThrottle = false, limit); - } - }; - }, - - /** - * 延迟执行 - * @param {number} ms - 延迟时间(毫秒) - * @returns {Promise} Promise对象 - */ - delay(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + goPage(url) { + uni.navigateTo({ + url + }); } }; @@ -465,7 +382,6 @@ export default { ...numberUtil, ...stringUtil, ...deviceUtil, - ...networkUtil, ...uiUtil, ...util };