Files
web_ylsa/web_vue/src/pages/account/index.vue
2025-07-11 16:54:11 +08:00

263 lines
7.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import { useRequest } from "vue-request";
import { myRequest } from "@/requests/request.ts";
import { ref } from "vue";
import _ from "lodash";
import { account, userinfo } from "@/store/store.ts";
import { ElMessage } from "element-plus";
import { formatError } from "@/utils/utils.ts";
import { Check, Close } from "@element-plus/icons-vue";
import { sum } from "lodash-es";
import YlActionDiv from "@/components/yl-action-div.vue";
const editData = ref({ card: "", type: false, balance: 0 });
const dialog = ref(false);
const page = ref(1);
const pageSize = ref(10);
const editYe = ref(false);
// const show = ref(false);
const { data, loading, run } = useRequest<{
data: { balance: number; type: boolean; card: string }[];
}>(() => myRequest(`/api/yeb`, userinfo.token));
const { runAsync: updateCard } = useRequest(
() =>
myRequest(
`/api/yeb`,
userinfo.token,
{ ...editData.value, balance: Number(editData.value.balance) },
"put",
),
{ manual: true },
);
const { runAsync: deleteCard } = useRequest(
(card: string) =>
myRequest(`/api/yeb`, userinfo.token, { card: card }, "delete"),
{ manual: true },
);
const { runAsync: addCard, loading: adding } = useRequest(
() =>
myRequest(
`/api/yeb`,
userinfo.token,
{ ...editData.value, balance: Number(editData.value.balance) },
"post",
),
{ manual: true },
);
const addCardBtn = () => {
editData.value = { card: "", type: false, balance: 0 };
dialog.value = true;
};
const addCardFunc = () => {
if (
!editData.value.card ||
(!editData.value.balance && editData.value.balance !== 0)
) {
ElMessage.error("参数格式错误");
return;
}
addCard()
.then((res) => {
editData.value = { card: "", type: false, balance: 0 };
ElMessage.success(res.data);
run();
dialog.value = false;
})
.catch((err) => ElMessage.error(formatError(err)));
};
const updateCardFunc = () => {
updateCard()
.then((res) => {
ElMessage.success(res.data);
run();
editData.value = { card: "", type: false, balance: 0 };
})
.catch((err) => ElMessage.error(formatError(err)));
};
const deleteCardFunc = (e: string) => {
deleteCard(e)
.then((res) => {
ElMessage.success(res.data);
run();
})
.catch((err) => ElMessage.error(formatError(err)));
};
const updateType = (
t: boolean,
d: { card: string; type: boolean; balance: number },
) => {
editData.value = { ...d, type: t };
updateCard()
.then((res) => {
ElMessage.success(res.data);
run();
editData.value = { card: "", type: false, balance: 0 };
})
.catch((err) => ElMessage.error(formatError(err)));
};
</script>
<template>
<yl-action-div>
<el-button link @click="addCardBtn">新增项目</el-button>
</yl-action-div>
<el-table
stripe
v-loading="loading"
:data="
_.get(data, 'data', []).filter(
(_: {}, index: number) =>
index >= (page - 1) * pageSize && index < page * pageSize,
)
"
>
<el-table-column prop="card" label="项目" align="center" />
<el-table-column prop="balance" label="余额(双击修改)" align="center">
<template #default="scope"
><div
v-if="scope.row.card !== editData.card"
class="balance-div"
:style="`color:${scope.row.type ? 'red' : ''}`"
@dblclick="
() => {
editYe = true;
editData = {
card: scope.row.card,
type: scope.row.type,
balance: scope.row.balance,
};
}
"
>
{{ account.show ? scope.row.balance : "******" }}
</div>
<div v-else-if="editYe" class="flex between">
<el-input
v-model="editData.balance"
type="number"
placeholder="输入当前余额"
:min="0"
:max="99999999"
style="width: calc(100% - 50px)"
>
<template #prefix></template>
</el-input>
<div v-if="editYe">
<el-icon color="green" size="20"
><i class="bi-check2" @click="updateCardFunc"
/></el-icon>
<el-icon
color="red"
size="20"
@click="editData = { card: '', type: false, balance: 0 }"
><i class="bi-x"
/></el-icon>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="支出型" align="center">
<template #default="scope">
<el-switch
v-model="scope.row.type"
inline-prompt
:loading="loading"
active-text=""
inactive-text=""
@change="
(t: boolean) => {
editYe = false;
updateType(t, scope.row);
}
"
/>
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-popconfirm
:title="`确认删除 ${scope.row.card} `"
cancel-button-text="取消"
confirm-button-text="确认"
@confirm="() => deleteCardFunc(scope.row.card)"
><template #reference
><el-icon color="red"><Close /></el-icon></template
></el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="flex between pagination-div">
<div>
<label>显示余额</label
><el-switch v-model="account.show">
<template #active-action><Check /></template>
<template #inactive-action><Close /></template> </el-switch
><label v-if="account.show">
合计{{
sum(data?.data.map((e) => (e.type ? -e.balance : e.balance))).toFixed(
2,
)
}}</label
>
</div>
<div>
<el-pagination
layout="sizes, prev, pager, next"
:total="_.get(data, 'data', []).length"
v-model:current-page="page"
v-model:page-size="pageSize"
:hide-on-single-page="pageSize === 10"
/>
</div>
</div>
<el-dialog title="新增项目" v-model="dialog">
<div class="input-div flex between">
<el-input v-model="editData.card" placeholder="输入项目名称" clearable>
<template #prefix>
<el-switch
v-model="editData.type"
active-text="借贷"
inactive-text="存款"
style="--el-switch-off-color: #606266; --el-switch-on-color: red"
inline-prompt
/>
</template>
</el-input>
</div>
<div class="input-div">
<el-input
v-model="editData.balance"
type="number"
placeholder="输入当前余额"
:min="0"
:max="99999999"
><template #prefix></template></el-input
>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="addCardFunc" :disabled="adding"
>保存</el-button
>
</div>
</template>
</el-dialog>
</template>
<style scoped>
.input-div {
margin: 1rem 2rem;
}
.dialog-footer {
padding-right: 2rem;
}
.balance-div:hover {
cursor: pointer;
}
.pagination-div {
padding: 1rem;
}
</style>