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 @@
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+ {{ item.classification }}
+
+
+ {{ item.time }}
+
+
+
+
+
+ {{ item.isAdd ? '+' : '-' }}{{ Number(item.money).toFixed(2) }}
+
+ 已全额退款
+ 余额 {{
+ Number(item.balance).toFixed(2)
+ }}元
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 @@
-
-
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+ {{ rightButtonText }}
+
+
+
+
+
+
+
+ {{ button.name }}
+
+
+
+
\ 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 @@
-
-
-
-
-
-
- 余额
-
-
-
-
-
-
-
- 资金安全有保障
-
-
-
- 可用余额(元)
-
-
-
- {{ Number(balance).toFixed(2) }}
-
-
-
-
- 提现
-
-
-
-
- 充值
-
-
-
-
-
-
-
-
-
-
-
-
\ 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 @@
+
+
+
+
+
+
+
+ 余额
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 资金安全有保障
+
+
+
+ 可用余额(元)
+
+
+
+ {{ Number(balance).toFixed(2) }}
+
+
+
+
+ 提现
+
+
+
+
+ 充值
+
+
+
+
+
+
+
+
+ 余额变动明细
+
+ 全部
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 @@
+
+
+
+
+
+
+
+
+ 搜索
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+ 筛选
+
+
+
+
+
+
+
+ {{ currentMonthData.month }}月
+
+
+
+
+ 支出¥{{
+ Number(currentMonthData.outCome).toFixed(2) }}
+ 收入¥{{
+ Number(currentMonthData.inCome).toFixed(2) }}
+
+
+ 收支分析
+
+
+
+
+
+
+
+ {{ item.month }}
+ 月
+
+
+
+
+
+
+ 收入
+ ¥{{
+ Number(item.inCome).toFixed(2)
+ }}
+
+
+ 支出
+ ¥{{
+ Number(item.outCome).toFixed(2)
+ }}
+
+
+
+ 收支分析
+
+
+
+
+ 设置支出预算
+
+
+
+ 收支分析
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 @@
-
-
-
-
-
-
-
- 日期处理
-
- 当前日期:
- {{ currentDate }}
-
-
- 格式化日期:
- {{ formattedDate }}
-
-
- 相对时间:
- {{ relativeDate }}
-
-
-
-
-
- 数字处理
-
- 千分位格式化:
- {{ formattedNumber }}
-
-
- 金额格式化:
- {{ formattedMoney }}
-
-
- 随机数:
- {{ randomNumber }}
-
-
-
-
-
- 字符串处理
-
- UUID:
- {{ uuid }}
-
-
- 手机号脱敏:
- {{ maskedPhone }}
-
-
- 字符串截断:
- {{ truncatedString }}
-
-
-
-
-
- UI工具
-
-
-
-
-
-
-
-
-
-
- 设备信息
-
- 状态栏高度:
- {{ statusBarHeight }}
-
-
- 设备平台:
- {{ devicePlatform }}
-
-
- 网络状态:
- {{ networkStatus }}
-
-
-
-
-
- 屏幕尺寸
-
- 屏幕宽度:
- {{ screenWidth }}
-
-
- 屏幕高度:
- {{ screenHeight }}
-
-
- 窗口宽度:
- {{ windowWidth }}
-
-
- 窗口高度:
- {{ windowHeight }}
-
-
-
-
-
-
-
-
-
-
-
-
\ 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