feat:增加奖状证书模块

This commit is contained in:
2026-04-01 23:24:06 +08:00
parent 11887bf3d5
commit ac914f6c05
60 changed files with 601 additions and 1095 deletions

35
src/apis/award.ts Normal file
View File

@@ -0,0 +1,35 @@
import { cloudService } from './index'
import { IAward, IAwardQuery } from '@/types/award.ts'
export const addAwardApi = (award: IAward): Promise<boolean> =>
cloudService({
url: '/home-api/award',
method: 'post',
data: award
})
export const updateAwardApi = (id: number, award: IAward): Promise<boolean> =>
cloudService({
url: `/home-api/award/${id}`,
method: 'put',
data: award
})
export const deleteAwardApi = (id: number): Promise<boolean> =>
cloudService({
url: `/home-api/award/${id}`,
method: 'delete'
})
export const queryAwardApi = (id: number): Promise<IAward> =>
cloudService({
url: `/home-api/award/${id}`,
method: 'get'
})
export const queryAwardListApi = (query: IAwardQuery): Promise<IAward[]> =>
cloudService({
url: '/home-api/award',
method: 'get',
params: query
})

View File

@@ -0,0 +1,96 @@
<template>
<div class="life-record-card card-item">
<el-image v-if="props.item?.imageList.length > 0"
:src="`${props.item?.imageList[0]}${ThumbImageQuery}`"
fit="contain" alt="暂无图片" @click="viewImageClick">
<template #error>
<div class="image-slot">
<span>暂无图片</span>
</div>
</template>
</el-image>
<el-empty v-else description="暂无图片" />
<van-swipe-cell>
<div class="record-info" @click="editClick()">
<div class="top-container">
<div class="info-list">
<div class="info-item">
<span class="title">{{ props.item.name }}</span>
</div>
</div>
</div>
<div class="bottom-container">
<div class="info-list">
<div class="info-item">
<i class="fa-solid fa-location-dot" style="color: #6A5ACD"></i>
{{ props.item.location }}
</div>
</div>
<div class="info-list">
<div class="info-item">
<i class="fa-solid fa-flag"></i>
{{ props.item.owner }}
</div>
<div class="info-item">
<i class="fa-regular fa-calendar-check"></i>
{{ props.item.date }}
</div>
</div>
</div>
</div>
<template #right>
<van-button square type="primary" text="编辑" style="height: 100%;"
@click="editClick"/>
<van-button square type="danger" text="删除" style="height: 100%;"
@click="deleteClick()"/>
</template>
</van-swipe-cell>
</div>
</template>
<script setup lang="ts">
import { useAwardStore } from '@/store/award.ts'
import { defineProps, PropType } from 'vue'
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
import { useRouter } from 'vue-router'
import { ThumbImageQuery } from '@/utils'
import { showImagePreview } from 'vant'
import { IAward } from '@/types/award.ts'
const awardStore = useAwardStore()
const router = useRouter()
const props = defineProps({
item: {
required: true,
type: Object as PropType<IAward>
}
})
const viewImageClick = () => {
showImagePreview({ images: props.item?.imageList, closeable: true })
}
const editClick = async () => {
const id = props.item?.id
awardStore.awardApiType = 'UPDATE'
awardStore.currentAward = props.item as IAward
await router.push({ name: 'AwardDetailId', params: { id } })
}
const deleteClick = () => {
awardStore.awardApiType = 'DELETE'
commonElMessageBox(`请确认是否删除该记录: ${props.item?.name}?`).then(() => {
awardStore.handleAwardApi(props.item as IAward)
})
}
</script>
<style lang="scss">
@use "@/styles/home/life.record.module";
</style>

View File

@@ -0,0 +1,30 @@
<template>
<div class="mobile-common-query card-item">
<div class="query-item">
<span>类型</span>
<el-segmented v-model="awardStore.queryInfo.type"
:options="queryTypeList"
@change="awardStore.queryAwardList()"/>
</div>
</div>
</template>
<script setup lang="ts">
import { useAwardStore } from '@/store/award.ts'
const awardStore = useAwardStore()
const queryTypeList = [
{
label: '全部',
value: ''
},
{
label: '证书',
value: 'certificate'
}, {
label: '奖状',
value: 'award'
}
]
</script>

View File

@@ -1,166 +0,0 @@
<template>
<div class="bill-setting">
<div class="button-container">
<el-button type="primary" @click="addNewBookClick">新增账本</el-button>
</div>
<el-table
:data="billStore.billBookList"
border stripe
:header-cell-style="tableHeaderStyle()"
:cell-style="tableCellStyle()"
:row-style="tableRowStyle()"
style="width: 100%"
class="card-item">
<el-table-column type="index" align="center" width="50"/>
<el-table-column prop="name" label="名称" align="center" width="100"/>
<el-table-column label="图标" align="center" width="80">
<template #default="scope">
<i :class="scope.row.icon" :style="{color: scope.row.color, fontSize: '24px'}"></i>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button type="primary" size="small" @click="editBookClick(scope.row)">编辑</el-button>
<el-button type="danger" size="small" @click="deleteBookClick(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="billInfo.billBookDialog.visible"
:title="billInfo.billBookDialog.title"
center width="80%" @open="openDialogEvent">
<el-form ref="formRef" :model="billInfo.billBookDialog.data"
:rules="rules" label-position="top" label-width="100px">
<el-form-item label="账本名称" prop="name">
<el-input v-model="billInfo.billBookDialog.data.name" autocomplete="off"
placeholder="请输入类型名称"
:maxlength="10" show-word-limit/>
</el-form-item>
<el-form-item label="类型图标" prop="icon">
<el-input v-model="billInfo.billBookDialog.data.icon" autocomplete="off"
placeholder="请输入类型图标"
:maxlength="40" show-word-limit/>
</el-form-item>
<el-form-item label="图标颜色" prop="color">
<el-color-picker v-model="billInfo.billBookDialog.data.color" />
</el-form-item>
<el-form-item label="图标预览">
<i :class="billInfo.billBookDialog.data.icon"
:style="{color: billInfo.billBookDialog.data.color, fontSize: '24px'}"></i>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelClick">取消</el-button>
<el-button type="primary" @click="confirmClick">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { nextTick, onMounted, reactive, ref } from 'vue'
import { useBillStore } from '@/store/bill.ts'
import { ElMessage, FormRules } from 'element-plus'
import { IBillBook } from '@/types/bill.ts'
import { billBookRules } from '@/utils/element/elRules.ts'
import { deepCopyObject } from 'vue3-common/utils/dataUtil'
import type { IDialog, IHandleApi } from 'vue3-common/types'
import { addBillBookApi, updateBillBookApi } from '@/apis/bill.ts'
import { tableCellStyle, tableHeaderStyle, tableRowStyle } from 'vue3-common/utils/elUtil'
const formRef = ref()
const rules = reactive<FormRules>(billBookRules)
const billStore = useBillStore()
const billInfo = reactive({
setBillBookType: 'ADD' as IHandleApi,
billBookDialog: {
title: '',
visible: false,
data: {}
} as IDialog<IBillBook>
})
onMounted(async () => {
await billStore.queryBillBook()
})
/**
* 点击新增账本按钮
*/
const addNewBookClick = () => {
billInfo.setBillBookType = 'ADD'
billInfo.billBookDialog = {
title: '新增账本',
visible: true,
data: {
name: '',
icon: '',
color: ''
}
}
}
/**
* 点击编辑账本按钮
* @param book 账本
*/
const editBookClick = async (book: IBillBook) => {
billInfo.setBillBookType = 'UPDATE'
billInfo.billBookDialog = {
title: '编辑账本',
visible: true,
data: deepCopyObject(book)
}
}
/**
* 点击删除账本按钮
* @param book 账本
*/
const deleteBookClick = (book: IBillBook) => {
billInfo.setBillBookType = 'DELETE'
ElMessage.error('暂不支持该功能')
}
const openDialogEvent = () => {
nextTick(() => {
formRef.value.clearValidate()
})
}
const setBillBookApi = async (id?: number) => {
switch (billInfo.setBillBookType) {
case 'ADD':
await addBillBookApi(billInfo.billBookDialog.data)
ElMessage.success('新增账本成功')
break
case 'UPDATE':
await updateBillBookApi(id as number, billInfo.billBookDialog.data)
ElMessage.success('更新账本成功')
break
case 'DELETE':
ElMessage.success('删除账本成功')
break
default:
break
}
await billStore.queryBillBook()
billInfo.billBookDialog.visible = false
}
const cancelClick = () => {
billInfo.billBookDialog.visible = false
}
const confirmClick = async () => {
await formRef.value.validate(async (valid) => {
if (valid) {
await setBillBookApi(billInfo.billBookDialog.data.id)
}
})
}
</script>

View File

@@ -1,222 +0,0 @@
<template>
<div class="bill-setting">
<div class="button-container">
<el-select
v-model="billInfo.bookName"
placeholder="请选择账本名称"
@focus="focusBookNameEvent"
@change="selectBookNameEvent"
style="width: 150px;">
<el-option
v-for="(item, index) in billInfo.billBookList"
:key="index" :label="item.name" :value="item.name"
/>
</el-select>
<el-button type="primary" @click="addNewCategoryClick">新增类别</el-button>
</div>
<el-table
:data="billInfo.billCategoryList"
border stripe
:header-cell-style="tableHeaderStyle()"
:cell-style="tableCellStyle()"
:row-style="tableRowStyle()"
class="card-item">
<el-table-column type="index" align="center" width="50"/>
<el-table-column prop="name" label="名称" align="center" width="80"/>
<el-table-column label="类型" align="center" width="80">
<template #default="scope">
<el-tag v-if="scope.row.type === 'expensive'" effect="dark" color="#CA6C65">支出</el-tag>
<el-tag v-else effect="dark" color="#6FBB69">收入</el-tag>
</template>
</el-table-column>
<el-table-column label="图标" align="center" width="80">
<template #default="scope">
<i :class="scope.row.icon" :style="{color: scope.row.color, fontSize: '24px'}"></i>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="150">
<template #default="scope">
<el-button type="primary" size="small" @click="editCategoryClick(scope.row)">编辑</el-button>
<el-button type="danger" size="small" @click="deleteCategoryClick(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="billInfo.billCategoryDialog.visible"
:title="billInfo.billCategoryDialog.title"
center width="80%" @open="openDialogEvent">
<el-form ref="formRef" :model="billInfo.billCategoryDialog.data"
:rules="rules" label-position="top" label-width="100px">
<el-form-item label="账本名称" prop="bookName">
<el-select
v-model="billInfo.billCategoryDialog.data.bookName"
placeholder="请选择账本名称"
@focus="focusBookNameEvent">
<el-option
v-for="(item, index) in billInfo.billBookList"
:key="index" :label="item.name" :value="item.name"
/>
</el-select>
</el-form-item>
<el-form-item label="类别名称" prop="name">
<el-input v-model="billInfo.billCategoryDialog.data.name" autocomplete="off"
placeholder="请输入类型名称"
:maxlength="10" show-word-limit/>
</el-form-item>
<el-form-item label="类型名称" prop="type">
<el-radio-group v-model="billInfo.billCategoryDialog.data.type">
<el-radio value="expensive">支出</el-radio>
<el-radio value="income">收入</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="类别图标" prop="icon">
<el-input v-model="billInfo.billCategoryDialog.data.icon" autocomplete="off"
placeholder="请输入类型图标"
:maxlength="40" show-word-limit/>
</el-form-item>
<el-form-item label="图标颜色" prop="color">
<el-color-picker v-model="billInfo.billCategoryDialog.data.color" />
</el-form-item>
<el-form-item label="图标预览">
<i :class="billInfo.billCategoryDialog.data.icon"
:style="{color: billInfo.billCategoryDialog.data.color, fontSize: '24px'}"></i>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelClick">取消</el-button>
<el-button type="primary" @click="confirmClick">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { nextTick, onMounted, reactive, ref } from 'vue'
import { useBillStore } from '@/store/bill.ts'
import { IBillBook, IBillCategory } from '@/types/bill.ts'
import { ElMessage, FormRules } from 'element-plus'
import { billCategoryRules } from '@/utils/element/elRules.ts'
import { addBillCategoryApi, updateBillCategoryApi } from '@/apis/bill.ts'
import { deepCopyObject } from 'vue3-common/utils/dataUtil'
import { tableHeaderStyle, tableRowStyle, tableCellStyle } from 'vue3-common/utils/elUtil'
import type { IDialog, IHandleApi } from 'vue3-common/types'
const formRef = ref()
const rules = reactive<FormRules>(billCategoryRules)
const billStore = useBillStore()
const billInfo = reactive({
bookName: '日常账本',
setBillCategoryType: 'ADD' as IHandleApi,
billCategoryDialog: {
title: '',
visible: false,
data: {}
} as IDialog<IBillCategory>,
billBookList: [] as IBillBook[],
billCategoryList: [] as IBillCategory[]
})
onMounted(async () => {
await billStore.queryBillCategory()
queryBookCategoryByBookName(billInfo.bookName)
})
const selectBookNameEvent = (value: string) => {
queryBookCategoryByBookName(value)
}
const queryBookCategoryByBookName = (bookName: string) => {
billInfo.billCategoryList = billStore.billCategoryList.filter((item) => {
return item.bookName === bookName
})
}
/**
* 点击新增类别按钮
*/
const addNewCategoryClick = () => {
billInfo.setBillCategoryType = 'ADD'
billInfo.billCategoryDialog = {
title: '新增账单类别',
visible: true,
data: {
bookName: '',
name: '',
type: '',
icon: '',
color: ''
}
}
}
/**
* 点击编辑类别按钮
* @param category 类别
*/
const editCategoryClick = async (category: IBillCategory) => {
billInfo.setBillCategoryType = 'UPDATE'
billInfo.billCategoryDialog = {
title: '编辑账单类别',
visible: true,
data: deepCopyObject(category)
}
}
/**
* 点击删除类别按钮
* @param category 类别
*/
const deleteCategoryClick = (category: IBillCategory) => {
billInfo.setBillCategoryType = 'DELETE'
ElMessage.error('暂不支持该功能')
}
const openDialogEvent = () => {
nextTick(() => {
formRef.value.clearValidate()
})
}
const focusBookNameEvent = async () => {
await billStore.queryBillBook()
billInfo.billBookList = billStore.billBookList
}
const setBillCategoryApi = async (id?: number) => {
switch (billInfo.setBillCategoryType) {
case 'ADD':
await addBillCategoryApi(billInfo.billCategoryDialog.data)
ElMessage.success('新增账单类别成功')
break
case 'UPDATE':
await updateBillCategoryApi(id as number, billInfo.billCategoryDialog.data)
ElMessage.success('更新账单类别成功')
break
case 'DELETE':
ElMessage.success('删除账单类别成功')
break
default:
break
}
await billStore.queryBillCategory()
billInfo.billCategoryDialog.visible = false
}
const cancelClick = () => {
billInfo.billCategoryDialog.visible = false
}
const confirmClick = async () => {
await formRef.value.validate(async (valid) => {
if (valid) {
await setBillCategoryApi(billInfo.billCategoryDialog.data.id)
queryBookCategoryByBookName(billInfo.bookName)
}
})
}
</script>

View File

@@ -1,166 +0,0 @@
<template>
<div class="bill-setting">
<div class="button-container">
<el-button type="primary" @click="addNewPayClick">新增账户</el-button>
</div>
<el-table
:data="billStore.billPayList"
border stripe
:header-cell-style="tableHeaderStyle()"
:cell-style="tableCellStyle()"
:row-style="tableRowStyle()"
style="width: 100%"
class="card-item">
<el-table-column type="index" align="center" width="50" />
<el-table-column prop="name" label="名称" align="center" width="100"/>
<el-table-column label="图标" align="center" width="80">
<template #default="scope">
<i :class="scope.row.icon" :style="{color: scope.row.color, fontSize: '24px'}"></i>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button type="primary" size="small" @click="editPayClick(scope.row)">编辑</el-button>
<el-button type="danger" size="small" @click="deletePayClick(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="billInfo.billPayDialog.visible"
:title="billInfo.billPayDialog.title"
center width="80%" @open="openDialogEvent">
<el-form ref="formRef" :model="billInfo.billPayDialog.data"
:rules="rules" label-position="top" label-width="100px">
<el-form-item label="账户名称" prop="name">
<el-input v-model="billInfo.billPayDialog.data.name" autocomplete="off"
placeholder="请输入类型名称"
:maxlength="10" show-word-limit/>
</el-form-item>
<el-form-item label="账户图标" prop="icon">
<el-input v-model="billInfo.billPayDialog.data.icon" autocomplete="off"
placeholder="请输入类型图标"
:maxlength="40" show-word-limit/>
</el-form-item>
<el-form-item label="图标颜色" prop="color">
<el-color-picker v-model="billInfo.billPayDialog.data.color" />
</el-form-item>
<el-form-item label="图标预览">
<i :class="billInfo.billPayDialog.data.icon"
:style="{color: billInfo.billPayDialog.data.color, fontSize: '24px'}"></i>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelClick">取消</el-button>
<el-button type="primary" @click="confirmClick">确认</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { nextTick, onMounted, reactive, ref } from 'vue'
import { useBillStore } from '@/store/bill.ts'
import { ElMessage, FormRules } from 'element-plus'
import { IBillPay } from '@/types/bill.ts'
import { billPayRules } from '@/utils/element/elRules.ts'
import { deepCopyObject } from 'vue3-common/utils/dataUtil'
import { addBillPayApi, updateBillPayApi } from '@/apis/bill.ts'
import { tableCellStyle, tableHeaderStyle, tableRowStyle } from 'vue3-common/utils/elUtil'
import type { IDialog, IHandleApi } from 'vue3-common/types'
const formRef = ref()
const rules = reactive<FormRules>(billPayRules)
const billStore = useBillStore()
const billInfo = reactive({
setBillPayType: 'ADD' as IHandleApi,
billPayDialog: {
title: '',
visible: false,
data: {}
} as IDialog<IBillPay>
})
onMounted(async () => {
await billStore.queryBillPay()
})
/**
* 点击新增账户按钮
*/
const addNewPayClick = () => {
billInfo.setBillPayType = 'ADD'
billInfo.billPayDialog = {
title: '新增账户',
visible: true,
data: {
name: '',
icon: '',
color: ''
}
}
}
/**
* 点击编辑账户按钮
* @param pay 账户
*/
const editPayClick = async (pay: IBillPay) => {
billInfo.setBillPayType = 'UPDATE'
billInfo.billPayDialog = {
title: '编辑账户',
visible: true,
data: deepCopyObject(pay)
}
}
/**
* 点击删除账户按钮
* @param pay 账户
*/
const deletePayClick = (pay: IBillPay) => {
billInfo.setBillPayType = 'DELETE'
ElMessage.error('暂不支持该功能')
}
const openDialogEvent = () => {
nextTick(() => {
formRef.value.clearValidate()
})
}
const setBillBookApi = async (id?: number) => {
switch (billInfo.setBillPayType) {
case 'ADD':
await addBillPayApi(billInfo.billPayDialog.data)
ElMessage.success('新增账户成功')
break
case 'UPDATE':
await updateBillPayApi(id as number, billInfo.billPayDialog.data)
ElMessage.success('更新账户成功')
break
case 'DELETE':
ElMessage.success('删除账户成功')
break
default:
break
}
await billStore.queryBillPay()
billInfo.billPayDialog.visible = false
}
const cancelClick = () => {
billInfo.billPayDialog.visible = false
}
const confirmClick = async () => {
await formRef.value.validate((valid) => {
if (valid) {
setBillBookApi(billInfo.billPayDialog.data.id)
}
})
}
</script>

View File

@@ -19,7 +19,7 @@
v-model="billStore.billType"
inline-prompt
active-value="income" inactive-value="expensive"
active-text="收入账单" inactive-text="支出账单"
active-text="收入" inactive-text="支出"
@change="billStore.refreshInfo(isStats)"
style="--el-switch-on-color: #6FBB69; --el-switch-off-color: #CA6C65;"
/>

View File

@@ -32,7 +32,3 @@ onMounted(async () => {
await billStore.searchInfo()
})
</script>
<style lang="scss">
@use "@/styles/home/bill.mobile.module";
</style>

View File

@@ -1,9 +1,9 @@
<template>
<div class="mobile-common-query">
<div class="common-query">
<el-select
v-model="foodStore.queryRecipe.name"
filterable clearable
placeholder="请选择菜谱名称"
filterable clearable placeholder="请选择菜谱名称"
style="width: 150px;"
@change="changeFoodNameEvent">
<el-option
v-for="(item, index) in foodStore.foodNameList"

View File

@@ -47,7 +47,7 @@ const getAverageCount = () => {
}
})
return foodStore.foodRecordList.length / Object.keys(result).length
return (foodStore.foodRecordList.length / Object.keys(result).length).toFixed(2)
}
}
</script>

View File

@@ -1,7 +1,7 @@
<template>
<div class="life-record-card card-item">
<el-image :src="`${props.productItem?.imageUrl}${ThumbImageQuery}`"
fit="contain" alt="暂无成果" @click="viewImageClick">
fit="contain" alt="暂无图片" @click="viewImageClick">
<template #error>
<div class="image-slot">
<span>暂无图片</span>
@@ -65,7 +65,7 @@ import { defineProps, PropType } from 'vue'
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
import { IProduct } from '@/types/product.ts'
import { useRouter } from 'vue-router'
import { AListUrl, ThumbImageQuery } from '@/utils'
import { ThumbImageQuery } from '@/utils'
import { showImagePreview } from 'vant'
const productStore = useProductStore()

View File

@@ -15,11 +15,6 @@
<i class="fa-solid fa-magnifying-glass"></i>
<span>搜索</span>
</router-link>
<router-link v-if="path.includes('bill')" to="/bill/setting"
@click="routerClick()" class="item">
<i class="fa-solid fa-gear"></i>
<span>设置</span>
</router-link>
<router-link v-if="path.includes('food')" to="/food/recipe"
@click="routerClick()" class="item">
@@ -143,6 +138,12 @@
<span>清单</span>
</router-link>
<router-link v-if="path.includes('award')" to="/award/list"
@click="routerClick()" class="item">
<i class="fa-solid fa-list-ul"></i>
<span>清单</span>
</router-link>
<router-link v-if="path.includes('server')" to="/server/monitor"
@click="routerClick()" class="item">
<i class="fa-solid fa-desktop"></i>

70
src/store/award.ts Normal file
View File

@@ -0,0 +1,70 @@
import { defineStore } from 'pinia'
import type { IHandleApi } from 'vue3-common/types'
import { ElMessage } from 'element-plus'
import { ImagePathEnum } from '@/types'
import { IAward, IAwardQuery } from '@/types/award.ts'
import { addAwardApi, deleteAwardApi, queryAwardListApi, updateAwardApi } from '@/apis/award.ts'
export const useAwardStore = defineStore('award', {
state: () => ({
awardList: [] as IAward[],
queryInfo: {
type: ''
} as IAwardQuery,
awardApiType: 'ADD' as IHandleApi,
currentAward: {
name: '',
type: '',
owner: '',
date: '',
imageList: [] as string[]
} as IAward,
awardImagePath: ImagePathEnum.AWARD,
pageInfo: {
currentPage: 1,
pageSize: 3,
totalSize: 1
},
isScrollEnd: false,
isRefresh: false
}),
actions: {
async queryAwardList() {
this.awardList = await queryAwardListApi(this.queryInfo)
},
async handleAwardApi(award: IAward) {
switch (this.awardApiType) {
case 'ADD':
await addAwardApi(award)
ElMessage.success('新增成功')
break
case 'UPDATE':
await updateAwardApi(award.id as number, award)
ElMessage.success('更新成功')
break
case 'DELETE':
await deleteAwardApi(award.id as number)
ElMessage.success('删除成功')
break
default:
break
}
},
async refreshInfo() {
await this.queryAwardList()
this.isRefresh = !this.isRefresh
},
getEmptyAward(): IAward {
return {
id: 0,
date: '',
name: '',
owner: '',
type: '',
location: '',
imageList: [],
remark: ''
}
}
}
})

View File

@@ -54,7 +54,6 @@ export const usePasswordStore = defineStore('password', {
default:
break
}
await this.refreshInfo()
},
async refreshInfo() {
await this.queryPasswordList()

View File

@@ -63,7 +63,6 @@ export const useProductStore = defineStore('product', {
default:
break
}
await this.refreshInfo()
},
async refreshInfo() {
await this.queryProductList()

View File

@@ -1,43 +0,0 @@
.mobile-bill-view {
display: flex;
flex-direction: column;
gap: 10px;
.el-date-editor {
align-self: center;
}
.el-switch {
.el-switch__core {
height: 32px;
width: 80px;
}
}
.bill-setting {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
display: flex;
gap: 10px;
}
}
.bill-search-list {
padding: 10px;
display: flex;
flex-direction: column;
gap: 10px;
.search-result-title {
align-self: flex-end;
display: flex;
gap: 10px;
}
}
}

View File

@@ -1,13 +0,0 @@
.mobile-food-view {
display: flex;
flex-direction: column;
gap: 10px;
.food-list {
display: flex;
flex-direction: column;
justify-content: space-between;
//align-items: center;
gap: 10px;
}
}

View File

@@ -1,20 +0,0 @@
.mobile-travel-view {
display: flex;
flex-direction: column;
gap: 10px;
.travel-list {
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
//align-items: center;
gap: 1vh;
.list {
display: flex;
flex-direction: column;
gap: 10px;
}
}
}

View File

@@ -82,4 +82,4 @@ span, input {
font-style: normal;
}
@import "//at.alicdn.com/t/c/font_4793264_jis1w9io0s8.css";
@import "//at.alicdn.com/t/c/font_4793264_ktq3tfln91.css";

View File

@@ -23,6 +23,24 @@ $tabBar-height: 70px;
background-color: var(--color-bg);
color: var(--color-text);
padding: 10px;
display: flex;
flex-direction: column;
gap: 10px;
.query-date {
align-self: center;
}
.content-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.form-button {
align-self: center;
}
}
.common-query {

14
src/types/award.ts Normal file
View File

@@ -0,0 +1,14 @@
export interface IAward {
id: number;
name: string;
type: string;
owner: string;
location: string;
date: string;
imageList: string[];
remark: string;
}
export interface IAwardQuery {
type: string;
}

View File

@@ -6,6 +6,7 @@ export enum ImagePathEnum {
PRODUCT = 'product',
JOURNAL = 'journal',
LEDGER = 'ledger',
AWARD = 'award',
USER = 'user'
}

View File

@@ -328,6 +328,24 @@ export const passwordRules = {
]
}
export const awardRules = {
name: [
{ required: true, message: '请输入证书名称', trigger: 'blur' }
],
type: [
{ required: true, message: '请选择证书类型', trigger: 'change' }
],
date: [
{ required: true, message: '请选择获取日期', trigger: 'change' }
],
location: [
{ required: true, message: '请输入获取地点', trigger: 'change' }
],
owner: [
{ required: true, message: '请选择所属人', trigger: 'change' }
]
}
export const accountRules = {
accountName: [
{ required: true, message: '请输入账号名称', trigger: 'blur' }

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-anniversary-detail common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="anniversaryStore.currentAnniversary"
:rules="rules" label-position="top" label-width="60px"
class="form-item">
@@ -46,7 +46,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button v-if="anniversaryStore.anniversaryApiType === 'UPDATE'"
type="danger" @click="deleteClick">删除</el-button>
@@ -112,15 +112,3 @@ const deleteClick = () => {
})
}
</script>
<style scoped lang="scss">
.mobile-anniversary-detail {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}
</style>

View File

@@ -1,10 +1,10 @@
<template>
<div class="mobile-anniversary-list common-mobile-view">
<div class="common-mobile-view">
<anniversary-query />
<el-empty v-if="anniversaryStore.anniversaryList.length === 0" />
<div v-else class="anniversary-list" v-loading="anniversaryStore.isLoading">
<div v-else class="content-list" v-loading="anniversaryStore.isLoading">
<anniversary-card v-for="(item, index) in anniversaryStore.anniversaryList"
:key="index" :date-item="item" />
</div>
@@ -35,17 +35,3 @@ const addClick = () => {
router.push({ name: 'AnniversaryDetailId', params: { id: 0 } })
}
</script>
<style lang="scss">
.mobile-anniversary-list {
display: flex;
flex-direction: column;
gap: 10px;
.anniversary-list {
display: flex;
flex-direction: column;
gap: 10px;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-asset-detail common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="assetStore.currentAssetRecord"
:rules="rules" label-position="top" label-width="auto"
class="form-item">
@@ -43,7 +43,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button v-if="assetStore.assetApiType === 'UPDATE'"
type="danger" @click="deleteClick">删除</el-button>
@@ -111,15 +111,3 @@ const deleteClick = () => {
})
}
</script>
<style scoped lang="scss">
.mobile-asset-detail {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}
</style>

View File

@@ -9,7 +9,7 @@
<el-empty v-if="assetStore.assetRecordList.length === 0" />
<div v-else class="asset-list">
<div v-else class="content-list">
<asset-card v-for="(item, index) in assetStore.assetList"
:key="index" :item="item"/>
</div>
@@ -42,10 +42,6 @@ const addClick = () => {
<style lang="scss">
.mobile-asset-list {
display: flex;
flex-direction: column;
gap: 10px;
.total-asset {
align-self: center;
display: flex;
@@ -62,11 +58,5 @@ const addClick = () => {
color: var(--el-color-primary);
}
}
.asset-list {
display: flex;
flex-direction: column;
gap: 10px;
}
}
</style>

View File

@@ -0,0 +1,158 @@
<template>
<div class="common-mobile-view">
<el-form ref="formRef" :model="awardStore.currentAward"
:rules="rules" label-position="top" label-width="80px"
class="form-item">
<el-form-item label="证书名称" prop="name">
<el-input v-model="awardStore.currentAward.name" autocomplete="off"
placeholder="请输入证书名称" clearable
show-word-limit maxlength="20">
</el-input>
</el-form-item>
<el-form-item label="证书类型" prop="type">
<el-radio-group v-model="awardStore.currentAward.type"
placeholder="请选择证书类型" clearable>
<el-radio
v-for="(item, index) in ['获奖', '技能', '身份', '财产']"
:key="index" :label="item" :value="item"
/>
</el-radio-group>
</el-form-item>
<el-form-item label="获取日期" prop="date">
<el-date-picker
v-model="awardStore.currentAward.date"
type="date" :editable="false" placeholder="请选择获取日期"
value-format="YYYY-MM-DD"/>
</el-form-item>
<el-form-item label="获取地点" prop="location">
<el-input v-model="awardStore.currentAward.location" autocomplete="off"
placeholder="请输入获取地点" clearable
show-word-limit maxlength="20">
</el-input>
</el-form-item>
<el-form-item label="所属人" prop="owner">
<el-select v-model="awardStore.currentAward.owner"
placeholder="请选择所属人" clearable>
<el-option
v-for="(item, index) in ['哥哥', '宝宝']"
:key="index" :label="item" :value="item"
/>
</el-select>
</el-form-item>
<el-form-item label="证书图片">
<el-upload
v-model:file-list="imageFileList"
list-type="picture-card"
:accept="acceptImageTypes"
:limit="3"
:before-upload="beforeUpload"
:http-request="httpRequest"
:on-success="handleSuccess"
:on-exceed="handleExceed"
:before-remove="beforeRemove"
:on-remove="handleRemove"
>
<el-icon><Plus /></el-icon>
<template #tip>
<div class="el-upload__tip">
请上传小于10M的图片
</div>
</template>
</el-upload>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="awardStore.currentAward.remark" autocomplete="off"
type="textarea" :rows="3"
placeholder="请输入备注" clearable
show-word-limit maxlength="100">
</el-input>
</el-form-item>
</el-form>
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button type="info" @click="cancelClick">取消</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { useAwardStore } from '@/store/award.ts'
import { useAppStore } from '@/store/app.ts'
import { ElMessage, ElMessageBox, FormRules, UploadProps, UploadRawFile, UploadRequestOptions, UploadUserFile } from 'element-plus'
import { awardRules } from '@/utils/element/elRules.ts'
import { onMounted, reactive, ref } from 'vue'
import { acceptImageTypes } from '@/utils/file.ts'
import { Plus } from '@element-plus/icons-vue'
import { beforeUploadImage, httpRequestFile } from '@/utils/element/elUpload.ts'
const formRef = ref()
const rules = reactive<FormRules>(awardRules)
const awardStore = useAwardStore()
const appStore = useAppStore()
const imageFileList = ref<UploadUserFile[]>([])
onMounted(async () => {
appStore.isShowMobileBack = true
initImageFileList()
})
const initImageFileList = () => {
imageFileList.value = []
awardStore.currentAward.imageList.forEach((image) => {
imageFileList.value.push({
name: 'image',
url: image
})
})
}
const beforeUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => {
return beforeUploadImage(rawFile)
}
const httpRequest: UploadProps['httpRequest'] = async (options: UploadRequestOptions): Promise<any> => {
return await httpRequestFile(awardStore.awardImagePath, options)
}
const handleSuccess = (response: string) => {
awardStore.currentAward.imageList.push(response)
}
const handleExceed: UploadProps['onExceed'] = () => {
ElMessage.warning('最多上传3张图片')
}
const handleRemove: UploadProps['onRemove'] = (uploadFile) => {
const index = imageFileList.value.findIndex((item) => item.uid === uploadFile.uid)
awardStore.currentAward.imageList.splice(index, 1)
}
const beforeRemove: UploadProps['beforeRemove'] = () => {
return ElMessageBox.confirm('确认删除该文件?').then(() => true, () => false)
}
/**
* 点击确认按钮
*/
const confirmClick = () => {
formRef.value.validate().then(async () => {
await awardStore.handleAwardApi(awardStore.currentAward)
history.back()
appStore.isShowMobileBack = false
})
}
const cancelClick = () => {
history.back()
appStore.isShowMobileBack = false
}
</script>

35
src/views/award/list.vue Normal file
View File

@@ -0,0 +1,35 @@
<template>
<div class="common-mobile-view">
<award-query />
<el-empty v-if="awardStore.awardList.length === 0" description="暂无记录"/>
<div v-else class="content-list">
<award-card v-for="(item, index) in awardStore.awardList"
:key="index" :item="item"/>
</div>
<van-floating-bubble icon="plus" @click="addClick" style="top: -60px;"/>
</div>
</template>
<script lang="ts" setup>
import AwardQuery from '@/components/Award/AwardQuery.vue'
import AwardCard from '@/components/Award/AwardCard.vue'
import { useAwardStore } from '@/store/award.ts'
import { onMounted } from 'vue'
import { useRouter } from 'vue-router'
const awardStore = useAwardStore()
const router = useRouter()
onMounted(async () => {
await awardStore.queryAwardList()
})
const addClick = () => {
awardStore.awardApiType = 'ADD'
awardStore.currentAward = awardStore.getEmptyAward()
router.push({ name: 'AwardDetailId', params: { id: 0 } })
}
</script>

View File

@@ -1,16 +1,18 @@
<template>
<div class="mobile-bill-view common-mobile-view">
<div class="common-mobile-view">
<bill-query />
<el-date-picker v-if="billStore.billDateType === 'month'"
v-model="billStore.billQueryForm.billMonth"
type="month" :editable="false" style="width: 120px;"
@change="billStore.refreshInfo()"/>
<div class="query-date">
<el-date-picker v-if="billStore.billDateType === 'month'"
v-model="billStore.billQueryForm.billMonth"
type="month" :editable="false" style="width: 120px;"
@change="billStore.refreshInfo()"/>
<el-date-picker v-if="billStore.billDateType === 'year'"
v-model="billStore.billQueryForm.billYear"
type="year" :editable="false" style="width: 120px;"
@change="billStore.refreshInfo()"/>
<el-date-picker v-if="billStore.billDateType === 'year'"
v-model="billStore.billQueryForm.billYear"
type="year" :editable="false" style="width: 120px;"
@change="billStore.refreshInfo()"/>
</div>
<bill-stats />
<bill-chart />
@@ -30,7 +32,3 @@ onMounted(async () => {
await billStore.refreshInfo(true)
})
</script>
<style lang="scss">
@use "@/styles/home/bill.mobile.module";
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-bill-view common-mobile-view">
<div class="common-mobile-view">
<bill-query/>
<bill-daily-list v-if="billStore.billDateType === 'year'"/>
<bill-calendar v-if="billStore.billDateType === 'month'" />
@@ -21,6 +21,8 @@ const billStore = useBillStore()
const router = useRouter()
onMounted(async () => {
await billStore.initBillInfo()
billStore.billQueryForm = {
billBook: 'all',
billYear: getCurrentYear(),
@@ -45,7 +47,3 @@ const addClick = () => {
router.push({ name: 'BillDetailId', params: { id: 0 } })
}
</script>
<style lang="scss">
@use "@/styles/home/bill.mobile.module";
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="bill-detail-mobile common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="billStore.currentBillRecord"
:rules="rules" label-position="top" label-width="80px"
class="form-item">
@@ -111,7 +111,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button v-if="billStore.billApiType === 'UPDATE'"
type="danger" @click="deleteClick">删除</el-button>
@@ -293,15 +293,3 @@ const deleteClick = () => {
})
}
</script>
<style scoped lang="scss">
.bill-detail-mobile {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-bill-view common-mobile-view">
<div class="common-mobile-view">
<bill-search />
<div v-if="billStore.billRecordList.length === 0">
@@ -64,5 +64,16 @@ const selectBillRecordClick = async (billRecord: IBillRecord) => {
</script>
<style lang="scss">
@use "@/styles/home/bill.mobile.module";
</style>
.bill-search-list {
padding: 10px;
display: flex;
flex-direction: column;
gap: 10px;
.search-result-title {
align-self: flex-end;
display: flex;
gap: 10px;
}
}</style>

View File

@@ -1,28 +0,0 @@
<template>
<div class="mobile-bill-view common-mobile-view">
<el-tabs v-model="activeName" type="card">
<el-tab-pane label="账本" name="book">
<bill-book />
</el-tab-pane>
<el-tab-pane label="账户" name="pay">
<bill-pay />
</el-tab-pane>
<el-tab-pane label="类别" name="category">
<bill-category />
</el-tab-pane>
</el-tabs>
</div>
</template>
<script lang="ts" setup>
import BillBook from '@/components/Bill/BillBook.vue'
import BillPay from '@/components/Bill/BillPay.vue'
import BillCategory from '@/components/Bill/BillCategory.vue'
import { ref } from 'vue'
const activeName = ref('book')
</script>
<style lang="scss">
@use "@/styles/home/bill.mobile.module";
</style>

View File

@@ -1,10 +1,10 @@
<template>
<div ref="foodRecipeRef" class="mobile-food-view common-mobile-view">
<div ref="foodRecipeRef" class="common-mobile-view">
<food-query />
<el-empty v-if="foodStore.foodRecipeList.length === 0" description="暂无美食记录"/>
<div v-else class="food-list">
<div v-else class="content-list">
<food-card v-for="(item, index) in foodStore.foodRecipeList"
:key="index" :food-item="item"/>
</div>
@@ -60,7 +60,3 @@ const addClick = () => {
router.push({ name: 'FoodRecipeForm' })
}
</script>
<style lang="scss">
@use "@/styles/home/food.mobile.module";
</style>

View File

@@ -47,14 +47,14 @@
</div>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" :disabled="activeStep === 0"
@click="previewClick">上一步</el-button>
<el-button type="primary" :disabled="activeStep === 2"
@click="nextClick">下一步</el-button>
</div>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button type="danger" @click="deleteClick">删除</el-button>
<el-button type="info" @click="cancelClick">取消</el-button>
@@ -125,14 +125,6 @@ const deleteClick = () => {
<style lang="scss">
.mobile-food-recipe-form {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
.material-form, .step-form {
display: flex;
flex-direction: column;

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-food-view common-mobile-view">
<div class="common-mobile-view">
<food-stats />
<food-calendar />
@@ -28,7 +28,3 @@ const addClick = () => {
router.push({ name: 'FoodRecordForm' })
}
</script>
<style lang="scss">
@use "@/styles/home/food.mobile.module";
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-food-record-form common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="foodStore.currentFoodRecord"
:rules="rules" label-position="top" label-width="80"
class="form-item">
@@ -58,7 +58,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button type="danger" @click="deleteClick">删除</el-button>
<el-button type="info" @click="cancelClick">取消</el-button>
@@ -151,13 +151,3 @@ const deleteClick = () => {
}
</script>
<style lang="scss">
.mobile-food-record-form {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}</style>

View File

@@ -1,10 +1,6 @@
<template>
<div class="mobile-food-timeline common-mobile-view ">
<div class="button-container">
<el-button :icon="CaretLeft" circle
type="primary" size="small"
@click="previousYearClick"/>
<div class="query-date">
<el-date-picker
v-model="foodStore.queryRecord.year"
type="year" placeholder="请选择年份"
@@ -12,10 +8,6 @@
style="width: 100px;"
@change="changeDateEvent"
/>
<el-button :icon="CaretRight" circle
type="primary" size="small"
@click="nextYearClick"/>
</div>
<el-timeline v-if="foodStore.foodRecordList.length > 0">
@@ -42,9 +34,8 @@
</template>
<script setup lang="ts">
import { CaretLeft, CaretRight } from '@element-plus/icons-vue'
import { useFoodStore } from '@/store/food.ts'
import { formatDate, getLastDate, getNextDate } from 'vue3-common/utils/dateUtil'
import { formatDate } from 'vue3-common/utils/dateUtil'
import { ThumbImageQuery } from '@/utils'
import { onMounted } from 'vue'
import { showImagePreview } from 'vant'
@@ -65,32 +56,10 @@ const changeDateEvent = async (value: Date) => {
foodStore.queryRecord.year = String(value.getFullYear())
await foodStore.queryFoodRecordList()
}
const previousYearClick = async () => {
const lastYear = getLastDate(foodStore.queryRecord.year, 1, 'years')
foodStore.queryRecord.year = String(new Date(lastYear).getFullYear())
await foodStore.queryFoodRecordList()
}
const nextYearClick = async () => {
const lastYear = getNextDate(foodStore.queryRecord.year, 1, 'years')
foodStore.queryRecord.year = String(new Date(lastYear).getFullYear())
await foodStore.queryFoodRecordList()
}
</script>
<style lang="scss">
.mobile-food-timeline {
display: flex;
flex-direction: column;
.button-container {
align-self: center;
display: flex;
align-items: center;
gap: 10px;
}
.el-timeline {
padding: 10px;

View File

@@ -1,9 +1,9 @@
<template>
<div class="mobile-health-view common-mobile-view">
<div class="common-mobile-view">
<v-calendar ref="calendarRef" :attributes='dailyInfo.attrs'
@dayclick="dateClick" @did-move="changeMonthClick"
:is-dark="appStore.isDark"
class="health-calendar card-item"/>
class="card-item"/>
<health-form />
</div>
@@ -62,17 +62,3 @@ const changeMonthClick = async (value) => {
await healthStore.refreshInfo()
}
</script>
<style lang="scss">
.mobile-health-view {
height: 100%;
display: flex;
flex-direction: column;
gap: 1vh;
.health-calendar {
justify-self: center;
align-self: center;
}
}
</style>

View File

@@ -1,8 +1,10 @@
<template>
<div class="mobile-bill-view common-mobile-view">
<el-date-picker v-model="healthStore.queryMonth"
type="month" :editable="false" style="width: 120px;"
@change="changeDateEvent"/>
<div class="common-mobile-view">
<div class="query-date">
<el-date-picker v-model="healthStore.queryMonth"
type="month" :editable="false" style="width: 120px;"
@change="changeDateEvent"/>
</div>
<health-stats />
<health-chart />
@@ -25,7 +27,3 @@ const changeDateEvent = async () => {
await healthStore.refreshInfo()
}
</script>
<style lang="scss">
@use "@/styles/home/bill.mobile.module";
</style>

View File

@@ -16,7 +16,7 @@
<div class="module-list">
<module-card icon="iconfont icon-zhangdan" color="#FFCC00"
title="账单记录" sub-title="收支一目了然"
router="/bill/data" @click="initBillClick"/>
router="/bill/data"/>
<module-card icon="iconfont icon-canyin" color="#FF8C32"
title="美食记录" sub-title="收录每日餐食"
@@ -61,6 +61,10 @@
<module-card icon="iconfont icon-ai-password" color="#4361EE"
title="密码管家" sub-title="守护数字安全"
router="/password/list"/>
<module-card icon="iconfont icon-zhengshu" color="#9B59B6"
title="奖状证书" sub-title="珍藏成长印记"
router="/award/list"/>
</div>
</main>
</template>
@@ -69,15 +73,9 @@
import WeatherTimeCard from '@/components/Common/WeatherTimeCard.vue'
import ModuleCard from '@/components/ModuleCard.vue'
import { useAppStore } from '@/store/app'
import { useBillStore } from '@/store/bill.ts'
import { getAssetsImageFile } from '@/utils'
const appStore = useAppStore()
const billStore = useBillStore()
const initBillClick = async () => {
await billStore.initBillInfo()
}
</script>
<style lang="scss">

View File

@@ -111,7 +111,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button v-if="journalStore.journalApiType === 'UPDATE'"
type="danger" @click="deleteClick">删除
@@ -241,19 +241,11 @@ const deleteClick = () => {
<style lang="scss">
.mobile-journal-detail {
display: flex;
flex-direction: column;
gap: 10px;
.el-radio {
.el-radio__label {
display: flex;
align-items: center;
}
}
.button-container {
align-self: center;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-journal-view common-mobile-view">
<div class="common-mobile-view">
<journal-calendar />
<van-floating-bubble icon="plus" @click="addClick" style="top: -60px;"/>
@@ -29,11 +29,3 @@ const addClick = () => {
router.push({ name: 'JournalDetailId', params: { id: 0 } })
}
</script>
<style lang="scss">
.mobile-journal-view {
display: flex;
flex-direction: column;
gap: 10px;
}
</style>

View File

@@ -1,11 +1,13 @@
<template>
<div class="mobile-journal-timeline common-mobile-view">
<el-date-picker
v-model="currentYear"
type="year" placeholder="请选择年份"
style="width: 100px"
@change="changeDateEvent"
/>
<div class="common-mobile-view">
<div class="query-date">
<el-date-picker
v-model="currentYear"
type="year" placeholder="请选择年份"
style="width: 100px"
@change="changeDateEvent"
/>
</div>
<el-timeline v-if="journalStore.journalList.length > 0" class="journal-timeline">
<el-timeline-item v-for="(item, index) in journalStore.journalList"
@@ -41,15 +43,3 @@ const changeDateEvent = async (value: Date) => {
await journalStore.refreshInfo()
}
</script>
<style lang="scss">
.mobile-journal-timeline {
display: flex;
flex-direction: column;
align-items: center;
.journal-timeline {
padding: 10px;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-kpi-detail common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="kpiStore.currentKpi"
:rules="rules" label-position="top" label-width="60px"
class="form-item">
@@ -43,7 +43,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button v-if="kpiStore.kpiApiType === 'UPDATE'"
type="danger" @click="deleteClick">删除
@@ -123,22 +123,3 @@ const deleteClick = () => {
})
}
</script>
<style lang="scss">
.mobile-kpi-detail {
display: flex;
flex-direction: column;
gap: 10px;
.el-radio {
.el-radio__label {
display: flex;
align-items: center;
}
}
.button-container {
align-self: center;
}
}
</style>

View File

@@ -41,10 +41,6 @@ const addClick = () => {
<style lang="scss">
.mobile-kpi-view {
display: flex;
flex-direction: column;
gap: 10px;
.total-kpi {
align-self: center;
display: flex;

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-ledger-detail common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="ledgerStore.currentLedgerRecord"
:rules="rules" label-position="top" label-width="auto"
class="form-item">
@@ -77,7 +77,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button v-if="ledgerStore.ledgerApiType === 'UPDATE'"
type="danger" @click="deleteClick">删除</el-button>
@@ -172,15 +172,3 @@ const deleteClick = () => {
})
}
</script>
<style scoped lang="scss">
.mobile-ledger-detail {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}
</style>

View File

@@ -9,7 +9,7 @@
<el-empty v-if="ledgerStore.ledgerRecordList.length === 0" />
<div v-else class="ledger-list">
<div v-else class="content-list">
<ledger-card v-for="(item, index) in ledgerStore.ledgerList"
:key="index" :item="item"/>
</div>
@@ -38,10 +38,6 @@ const addClick = () => {
<style lang="scss">
.mobile-ledger-list {
display: flex;
flex-direction: column;
gap: 10px;
.total-ledger {
align-self: center;
display: flex;
@@ -58,11 +54,5 @@ const addClick = () => {
color: var(--el-color-primary);
}
}
.ledger-list {
display: flex;
flex-direction: column;
gap: 10px;
}
}
</style>

View File

@@ -23,10 +23,6 @@ export const mobileHomeMeta: IRouteMetaConfig = {
title: '账单内容',
icon: ''
},
'/bill/setting': {
title: '账单设置',
icon: ''
},
'/food': {
title: '美食记录',
icon: '',
@@ -221,10 +217,24 @@ export const mobileHomeMeta: IRouteMetaConfig = {
title: '清单',
icon: ''
},
'/award': {
title: '奖状证书',
icon: 'home-award',
order: 13,
redirect: '/award/list'
},
'/award/list': {
title: '清单',
icon: ''
},
'/award/detail/id': {
title: '内容',
icon: ''
},
'/profile': {
title: '个人信息',
icon: '',
order: 13,
order: 14,
hidden: true,
redirect: '/profile/index'
},

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-password-detail common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="passwordStore.currentPassword"
:rules="rules" label-position="top" label-width="70px"
class="form-item">
@@ -62,7 +62,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button v-if="passwordStore.passwordApiType === 'UPDATE'"
type="danger" @click="deleteClick">删除</el-button>
@@ -112,15 +112,3 @@ const cancelClick = () => {
appStore.isShowMobileBack = false
}
</script>
<style scoped lang="scss">
.mobile-password-detail {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}
</style>

View File

@@ -1,10 +1,10 @@
<template>
<div class="mobile-product-list common-mobile-view">
<div class="common-mobile-view">
<password-query />
<el-empty v-if="passwordStore.passwordList.length === 0" description="暂无密码记录"/>
<div v-else class="product-list">
<div v-else class="content-list">
<password-card v-for="(item, index) in passwordStore.passwordList"
:key="index" :password-item="item"/>
</div>
@@ -33,17 +33,3 @@ const addClick = () => {
router.push({ name: 'PasswordDetailId', params: { id: 0 } })
}
</script>
<style lang="scss">
.mobile-product-list {
display: flex;
flex-direction: column;
gap: 10px;
.product-list {
display: flex;
flex-direction: column;
gap: 10px;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-period-view common-mobile-view">
<div class="common-mobile-view">
<v-calendar ref="calendarRef" :attributes='dailyInfo.attrs'
@dayclick="dateClick" @did-move="changeMonthClick"
:is-dark="appStore.isDark"
@@ -170,17 +170,3 @@ const getLastMonth = (current: string): string => {
return previousMonth.format('YYYY-MM')
}
</script>
<style lang="scss">
.mobile-period-view {
height: 100%;
display: flex;
flex-direction: column;
gap: 1vh;
.period-calendar {
justify-self: center;
align-self: center;
}
}
</style>

View File

@@ -1,7 +1,7 @@
<template>
<div class="mobile-period-setting common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="periodStore.periodSetting"
label-width="auto">
label-width="auto" class="form-item">
<el-form-item label="周期天数">
<el-input-number v-model="periodStore.periodSetting.cycleLength" autocomplete="off"
placeholder="请输入周期天数" clearable>
@@ -23,7 +23,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button type="info" @click="cancelClick">取消</el-button>
</div>
@@ -57,15 +57,3 @@ const cancelClick = () => {
history.back()
}
</script>
<style scoped lang="scss">
.mobile-period-setting {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-product-detail common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="productStore.currentProduct"
:rules="rules" label-position="top" label-width="80px"
class="form-item">
@@ -84,7 +84,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button type="info" @click="cancelClick">取消</el-button>
</div>
@@ -165,15 +165,3 @@ const cancelClick = () => {
appStore.isShowMobileBack = false
}
</script>
<style scoped lang="scss">
.mobile-product-detail {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}
</style>

View File

@@ -1,10 +1,10 @@
<template>
<div class="mobile-product-list common-mobile-view">
<div class="common-mobile-view">
<product-query />
<el-empty v-if="productStore.productList.length === 0" description="暂无物品记录"/>
<div v-else class="product-list">
<div v-else class="content-list">
<product-card v-for="(item, index) in productStore.productList"
:key="index" :product-item="item"/>
</div>
@@ -33,17 +33,3 @@ const addClick = () => {
router.push({ name: 'ProductDetailId', params: { id: 0 } })
}
</script>
<style lang="scss">
.mobile-product-list {
display: flex;
flex-direction: column;
gap: 10px;
.product-list {
display: flex;
flex-direction: column;
gap: 10px;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-travel-view common-mobile-view">
<div class="common-mobile-view">
<travel-stats />
<travel-calendar />
@@ -28,7 +28,3 @@ const addClick = () => {
router.push({ name: 'TravelRecordForm' })
}
</script>
<style lang="scss">
@use "@/styles/home/travel.mobile.module";
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-travel-record-form common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="travelStore.currentTravelRecord"
:rules="rules" label-position="top" label-width="auto"
class="form-item">
@@ -72,7 +72,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button type="danger" @click="deleteClick">删除</el-button>
<el-button type="info" @click="cancelClick">取消</el-button>
@@ -198,21 +198,3 @@ const deleteClick = () => {
})
}
</script>
<style lang="scss">
.mobile-travel-record-form {
display: flex;
flex-direction: column;
gap: 10px;
.video-list {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.button-container {
align-self: center;
}
}</style>

View File

@@ -1,14 +1,12 @@
<template>
<div ref="travelSpotRef" class="mobile-travel-view common-mobile-view">
<div ref="travelSpotRef" class="common-mobile-view">
<travel-query />
<div class="travel-list">
<el-empty v-if="travelStore.travelSpotList.length === 0" description="暂无旅行记录"/>
<el-empty v-if="travelStore.travelSpotList.length === 0" description="暂无旅行记录"/>
<div v-else class="list">
<travel-card v-for="(item, index) in travelStore.travelSpotList"
:key="index" :travel-item="item"/>
</div>
<div v-else class="content-list">
<travel-card v-for="(item, index) in travelStore.travelSpotList"
:key="index" :travel-item="item"/>
</div>
<van-floating-bubble icon="plus" @click="addClick" style="top: -60px;"/>
@@ -63,7 +61,3 @@ const addClick = () => {
router.push({ name: 'TravelSpotForm' })
}
</script>
<style lang="scss">
@use "@/styles/home/travel.mobile.module";
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="mobile-travel-spot-form common-mobile-view">
<div class="common-mobile-view">
<el-form ref="formRef" :model="travelStore.currentTravelSpot"
:rules=rules label-position="top" label-width="auto"
class="form-item">
@@ -72,7 +72,7 @@
</el-form-item>
</el-form>
<div class="button-container">
<div class="form-button">
<el-button type="primary" @click="confirmClick">确认</el-button>
<el-button type="info" @click="cancelClick">取消</el-button>
</div>
@@ -113,14 +113,3 @@ const cancelClick = () => {
appStore.isShowMobileBack = false
}
</script>
<style lang="scss">
.mobile-travel-spot-form {
display: flex;
flex-direction: column;
gap: 10px;
.button-container {
align-self: center;
}
}</style>