diff --git a/fund-mobile/components.d.ts b/fund-mobile/components.d.ts index 191b730..3239f8d 100644 --- a/fund-mobile/components.d.ts +++ b/fund-mobile/components.d.ts @@ -11,7 +11,11 @@ declare module 'vue' { RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] Tabbar: typeof import('./src/components/Tabbar.vue')['default'] + VanButton: typeof import('vant/es')['Button'] + VanCellGroup: typeof import('vant/es')['CellGroup'] VanDatePicker: typeof import('vant/es')['DatePicker'] + VanField: typeof import('vant/es')['Field'] + VanForm: typeof import('vant/es')['Form'] VanIcon: typeof import('vant/es')['Icon'] VanList: typeof import('vant/es')['List'] VanNavBar: typeof import('vant/es')['NavBar'] diff --git a/fund-mobile/src/api/index.ts b/fund-mobile/src/api/index.ts index 7a094cc..8e591bf 100644 --- a/fund-mobile/src/api/index.ts +++ b/fund-mobile/src/api/index.ts @@ -16,7 +16,7 @@ export function logout() { // ===================== 项目管理 ===================== -export function getProjectList(params?: { pageNum: number; pageSize: number; projectName?: string }) { +export function getProjectList(params?: { pageNum: number; pageSize: number; keyword?: string }) { return request.get('/project/page', { params }) } @@ -24,19 +24,45 @@ export function getProjectById(id: number) { return request.get(`/project/${id}`) } +export function createProject(data: any) { + return request.post('/project', data) +} + +// ===================== 需求工单管理 ===================== + +export function getRequirementList(params?: { pageNum: number; pageSize: number; keyword?: string }) { + return request.get('/requirement/page', { params }) +} + +export function getRequirementById(id: number) { + return request.get(`/requirement/${id}`) +} + +export function createRequirement(data: any) { + return request.post('/requirement', data) +} + // ===================== 客户管理 ===================== -export function getCustomerList(params?: { pageNum: number; pageSize: number; customerName?: string }) { +export function getCustomerList(params?: { pageNum: number; pageSize: number; keyword?: string }) { return request.get('/customer/page', { params }) } +export function getCustomerById(id: number) { + return request.get(`/customer/${id}`) +} + +export function createCustomer(data: any) { + return request.post('/customer', data) +} + // ===================== 支出管理 ===================== export function createExpense(data: any) { return request.post('/exp/expense', data) } -export function getExpenseList(params: { pageNum: number; pageSize: number }) { +export function getExpenseList(params?: { pageNum: number; pageSize: number; title?: string }) { return request.get('/exp/expense/page', { params }) } @@ -50,10 +76,18 @@ export function getTodayExpense() { // ===================== 应收款管理 ===================== -export function getReceivableList(params: { pageNum: number; pageSize: number; status?: string }) { +export function getReceivableList(params?: { pageNum: number; pageSize: number; status?: string; keyword?: string }) { return request.get('/receipt/receivable/page', { params }) } +export function getReceivableById(id: number) { + return request.get(`/receipt/receivable/${id}`) +} + +export function createReceivable(data: any) { + return request.post('/receipt/receivable', data) +} + export function getUpcomingDueList(daysWithin: number = 7) { return request.get(`/receipt/receivable/upcoming-due?daysWithin=${daysWithin}`) } diff --git a/fund-mobile/src/router/index.ts b/fund-mobile/src/router/index.ts index a3a3958..fa72a96 100644 --- a/fund-mobile/src/router/index.ts +++ b/fund-mobile/src/router/index.ts @@ -10,36 +10,79 @@ const router = createRouter({ component: () => import('@/views/Home.vue'), meta: { title: '首页', requiresAuth: true } }, + // 需求工单 + { + path: '/requirement', + name: 'RequirementList', + component: () => import('@/views/requirement/List.vue'), + meta: { title: '需求工单', requiresAuth: true } + }, + { + path: '/requirement/add', + name: 'RequirementAdd', + component: () => import('@/views/requirement/Add.vue'), + meta: { title: '新增需求工单', requiresAuth: true } + }, + // 支出管理 + { + path: '/expense', + name: 'ExpenseList', + component: () => import('@/views/expense/List.vue'), + meta: { title: '支出管理', requiresAuth: true } + }, { path: '/expense/add', name: 'ExpenseAdd', component: () => import('@/views/expense/Add.vue'), meta: { title: '新增支出', requiresAuth: true } }, + // 应收款管理 { path: '/receivable', name: 'ReceivableList', component: () => import('@/views/receivable/List.vue'), - meta: { title: '应收款列表', requiresAuth: true } + meta: { title: '应收款管理', requiresAuth: true } }, + { + path: '/receivable/add', + name: 'ReceivableAdd', + component: () => import('@/views/receivable/Add.vue'), + meta: { title: '新增应收款', requiresAuth: true } + }, + // 项目管理 { path: '/project', name: 'ProjectList', component: () => import('@/views/project/List.vue'), - meta: { title: '项目列表', requiresAuth: true } + meta: { title: '项目管理', requiresAuth: true } }, + { + path: '/project/add', + name: 'ProjectAdd', + component: () => import('@/views/project/Add.vue'), + meta: { title: '新增项目', requiresAuth: true } + }, + // 客户管理 { path: '/customer', name: 'CustomerList', component: () => import('@/views/customer/List.vue'), - meta: { title: '客户列表', requiresAuth: true } + meta: { title: '客户管理', requiresAuth: true } }, + { + path: '/customer/add', + name: 'CustomerAdd', + component: () => import('@/views/customer/Add.vue'), + meta: { title: '新增客户', requiresAuth: true } + }, + // 我的 { path: '/my', name: 'My', component: () => import('@/views/my/Index.vue'), meta: { title: '我的', requiresAuth: true } }, + // 登录 { path: '/login', name: 'Login', diff --git a/fund-mobile/src/views/Home.vue b/fund-mobile/src/views/Home.vue index 188a3dc..84564e6 100644 --- a/fund-mobile/src/views/Home.vue +++ b/fund-mobile/src/views/Home.vue @@ -43,41 +43,100 @@ - +
快捷操作
+
+
+ +
+
新增需求
+
+
+
+ +
+
新增应收款
+
-
- +
+
新增支出
-
-
- -
-
应收款
-
-
-
+
+
-
项目
+
新增项目
-
-
+
+
-
客户
+
新增客户
-
-
- +
+
+ + +
+
+ 业务服务 +
+
+
+
+
-
我的
+
+
需求工单
+
管理需求工单流程
+
+ +
+
+
+ +
+
+
应收款管理
+
跟踪应收款项
+
+ +
+
+
+ +
+
+
支出管理
+
管理支出审批流程
+
+ +
+
+
+ +
+
+
项目管理
+
项目信息管理
+
+ +
+
+
+ +
+
+
客户管理
+
客户信息管理
+
+
@@ -240,23 +299,25 @@ onMounted(() => { color: var(--mac-text-secondary); } +/* 快捷操作样式 */ .quick-card { + margin-bottom: 16px; padding: 20px; } .quick-grid { display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 16px; + grid-template-columns: repeat(5, 1fr); + gap: 8px; } .quick-item { display: flex; flex-direction: column; align-items: center; - padding: 16px 8px; + padding: 12px 4px; background: rgba(0, 0, 0, 0.02); - border-radius: 16px; + border-radius: 12px; cursor: pointer; transition: all 0.2s ease; } @@ -267,22 +328,121 @@ onMounted(() => { } .quick-icon { - width: 48px; - height: 48px; - border-radius: 14px; - background: linear-gradient(135deg, var(--mac-primary), #5AC8FA); + width: 40px; + height: 40px; + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + color: #fff; + margin-bottom: 8px; +} + +.quick-icon.requirement { + background: linear-gradient(135deg, #5856D6, #AF52DE); +} + +.quick-icon.receivable { + background: linear-gradient(135deg, #34C759, #30D158); +} + +.quick-icon.expense { + background: linear-gradient(135deg, #FF3B30, #FF453A); +} + +.quick-icon.project { + background: linear-gradient(135deg, #007AFF, #5AC8FA); +} + +.quick-icon.customer { + background: linear-gradient(135deg, #FF9500, #FF9F0A); +} + +.quick-text { + font-size: 11px; + font-weight: 500; + color: var(--mac-text); + text-align: center; +} + +/* 业务服务样式 */ +.service-card { + padding: 20px; + margin-bottom: 16px; +} + +.service-list { + display: flex; + flex-direction: column; + gap: 12px; +} + +.service-item { + display: flex; + align-items: center; + padding: 14px; + background: rgba(0, 0, 0, 0.02); + border-radius: 12px; + cursor: pointer; + transition: all 0.2s ease; +} + +.service-item:active { + background: rgba(0, 122, 255, 0.08); +} + +.service-icon { + width: 44px; + height: 44px; + border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 22px; color: #fff; - margin-bottom: 10px; - box-shadow: 0 4px 12px rgba(0, 122, 255, 0.25); + margin-right: 14px; + flex-shrink: 0; } -.quick-text { - font-size: 13px; - font-weight: 500; +.service-icon.requirement { + background: linear-gradient(135deg, #5856D6, #AF52DE); +} + +.service-icon.receivable { + background: linear-gradient(135deg, #34C759, #30D158); +} + +.service-icon.expense { + background: linear-gradient(135deg, #FF3B30, #FF453A); +} + +.service-icon.project { + background: linear-gradient(135deg, #007AFF, #5AC8FA); +} + +.service-icon.customer { + background: linear-gradient(135deg, #FF9500, #FF9F0A); +} + +.service-content { + flex: 1; +} + +.service-name { + font-size: 15px; + font-weight: 600; color: var(--mac-text); + margin-bottom: 4px; +} + +.service-desc { + font-size: 12px; + color: var(--mac-text-secondary); +} + +.service-arrow { + color: var(--mac-text-secondary); + font-size: 14px; } diff --git a/fund-mobile/src/views/customer/Add.vue b/fund-mobile/src/views/customer/Add.vue new file mode 100644 index 0000000..a72903b --- /dev/null +++ b/fund-mobile/src/views/customer/Add.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/fund-mobile/src/views/customer/List.vue b/fund-mobile/src/views/customer/List.vue index 247ca28..32d59ff 100644 --- a/fund-mobile/src/views/customer/List.vue +++ b/fund-mobile/src/views/customer/List.vue @@ -77,7 +77,7 @@ const loadData = async () => { const res: any = await getCustomerList({ pageNum: pageNum.value, pageSize, - customerName: searchText.value || undefined + keyword: searchText.value || undefined }) const records = res.data?.records || [] if (pageNum.value === 1) { diff --git a/fund-mobile/src/views/expense/List.vue b/fund-mobile/src/views/expense/List.vue new file mode 100644 index 0000000..40a5f99 --- /dev/null +++ b/fund-mobile/src/views/expense/List.vue @@ -0,0 +1,224 @@ + + + + + diff --git a/fund-mobile/src/views/project/Add.vue b/fund-mobile/src/views/project/Add.vue new file mode 100644 index 0000000..906e00c --- /dev/null +++ b/fund-mobile/src/views/project/Add.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/fund-mobile/src/views/project/List.vue b/fund-mobile/src/views/project/List.vue index b0c7c4c..8efae3c 100644 --- a/fund-mobile/src/views/project/List.vue +++ b/fund-mobile/src/views/project/List.vue @@ -92,7 +92,7 @@ const loadData = async () => { const res: any = await getProjectList({ pageNum: pageNum.value, pageSize, - projectName: searchText.value || undefined + keyword: searchText.value || undefined }) const records = res.data?.records || [] if (pageNum.value === 1) { diff --git a/fund-mobile/src/views/receivable/Add.vue b/fund-mobile/src/views/receivable/Add.vue new file mode 100644 index 0000000..be0db92 --- /dev/null +++ b/fund-mobile/src/views/receivable/Add.vue @@ -0,0 +1,221 @@ + + + + + diff --git a/fund-mobile/src/views/receivable/List.vue b/fund-mobile/src/views/receivable/List.vue index 7945d92..2d0a23b 100644 --- a/fund-mobile/src/views/receivable/List.vue +++ b/fund-mobile/src/views/receivable/List.vue @@ -4,10 +4,15 @@
- 应收款列表 + 应收款管理
+ + +
@@ -37,6 +42,11 @@
+ + +
+ +
@@ -45,6 +55,7 @@ import { ref, onMounted } from 'vue' import { showToast } from 'vant' import { getReceivableList } from '@/api' +const searchText = ref('') const loading = ref(false) const refreshing = ref(false) const finished = ref(false) @@ -72,20 +83,34 @@ const getStatusName = (status: string) => { return map[status] || status } -const onLoad = async () => { +const loadData = async () => { try { - const res: any = await getReceivableList({ pageNum: pageNum.value, pageSize }) + const res: any = await getReceivableList({ + pageNum: pageNum.value, + pageSize, + keyword: searchText.value || undefined + }) const records = res.data?.records || [] - list.value.push(...records) - loading.value = false - if (records.length < pageSize) { - finished.value = true + if (pageNum.value === 1) { + list.value = records } else { - pageNum.value++ + list.value.push(...records) } + finished.value = records.length < pageSize + loading.value = false } catch (e: any) { showToast(e.message || '加载失败') loading.value = false + finished.value = true + } +} + +const onLoad = () => { + if (pageNum.value === 1 && list.value.length === 0) { + loadData() + } else { + pageNum.value++ + loadData() } } @@ -94,17 +119,25 @@ const onRefresh = () => { pageNum.value = 1 finished.value = false refreshing.value = false - onLoad() + loadData() +} + +const handleSearch = () => { + pageNum.value = 1 + finished.value = false + list.value = [] + loadData() } onMounted(() => { - onLoad() + loadData() }) diff --git a/fund-mobile/src/views/requirement/Add.vue b/fund-mobile/src/views/requirement/Add.vue new file mode 100644 index 0000000..78adda4 --- /dev/null +++ b/fund-mobile/src/views/requirement/Add.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/fund-mobile/src/views/requirement/List.vue b/fund-mobile/src/views/requirement/List.vue new file mode 100644 index 0000000..73836e1 --- /dev/null +++ b/fund-mobile/src/views/requirement/List.vue @@ -0,0 +1,240 @@ + + + + +