feat: 初始化项目配置和文档- 添加 .editorconfig 文件,配置代码编辑规范

- 添加 .env 及相关文件,配置环境变量
- 添加 .eslintignore 和 .eslintrc.js 文件,配置 ESLint 规则
- 添加 .gitignore 文件,配置 Git忽略项
- 添加 .prettierignore 文件,配置 Prettier 忽略项
- 添加隐私政策文档,详细说明用户数据的收集和使用
This commit is contained in:
2025-08-23 20:31:46 +08:00
commit 37f3b6327c
1310 changed files with 210439 additions and 0 deletions

View File

@@ -0,0 +1,308 @@
<template>
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<template #extra>
<Extra/>
</template>
<a-card :bordered="false">
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="logId"
:columns="columns"
:datasource="datasource"
:scroll="{ x: 1000 }"
:where="defaultWhere"
cache-key="userBalanceLogTable"
>
<template #toolbar>
<a-space>
<!-- <a-button-->
<!-- danger-->
<!-- type="primary"-->
<!-- class="ele-btn-icon"-->
<!-- @click="removeBatch"-->
<!-- >-->
<!-- <template #icon>-->
<!-- <delete-outlined />-->
<!-- </template>-->
<!-- <span>批量删除</span>-->
<!-- </a-button>-->
<a-range-picker
v-model:value="dateRange"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
<a-input-search
allow-clear
v-model:value="searchText"
placeholder="请输入关键词"
@search="reload"
@pressEnter="reload"
/>
<a-button @click="reset">重置</a-button>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'nickname'">
<a-tooltip :title="`用户ID${record.userId}`">
<a @click="onSearch(record)">{{ record.nickname }}</a>
</a-tooltip>
</template>
<template v-if="column.key === 'scene'">
<a-tag v-if="record.scene === 10"> 用户充值 </a-tag>
<a-tag v-if="record.scene === 20"> 用户消费 </a-tag>
<a-tag v-if="record.scene === 30"> 管理员操作 </a-tag>
<a-tag v-if="record.scene === 40"> 订单退款 </a-tag>
</template>
<template v-if="column.key === 'money'">
<span
class="ele-text-success"
v-if="record.scene === 10 || record.scene === 40"
>
+{{ formatNumber(record.money) }}
</span>
<template v-else-if="record.scene === 30">
<span v-if="record.money > 0" class="ele-text-success">
+{{ formatNumber(record.money) }}
</span>
<span v-else class="ele-text-danger">
-{{ formatNumber(record.money * -1) }}
</span>
</template>
<span class="ele-text-danger" v-else>
-{{ formatNumber(record.money) }}
</span>
</template>
<template v-if="column.key === 'balance'">
<span> {{ formatNumber(record.balance) }} </span>
</template>
<!-- <template v-else-if="column.key === 'status'">-->
<!-- <a-switch-->
<!-- :checked="record.status === 0"-->
<!-- @change="(checked: boolean) => editStatus(checked, record)"-->
<!-- />-->
<!-- </template>-->
<!-- <template v-else-if="column.key === 'action'">-->
<!-- <a-space>-->
<!-- <a @click="openEdit(record)">修改</a>-->
<!-- <a-divider type="vertical" />-->
<!-- <a @click="resetPsw(record)">重置密码</a>-->
<!-- <a-divider type="vertical" />-->
<!-- <a-popconfirm-->
<!-- placement="topRight"-->
<!-- title="确定要删除此用户吗?"-->
<!-- @confirm="remove(record)"-->
<!-- >-->
<!-- <a class="ele-text-danger">删除</a>-->
<!-- </a-popconfirm>-->
<!-- </a-space>-->
<!-- </template>-->
</template>
</ele-pro-table>
</a-card>
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref, reactive } from 'vue';
import { message, Modal } from 'ant-design-vue/es';
import {
DeleteOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro/es';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import { toDateString, messageLoading, formatNumber } from 'ele-admin-pro/es';
import {
pageUserBalanceLog,
removeUserBalanceLog,
removeUserBalanceLogs
} from '@/api/user/balance-log';
import {
UserBalanceLog,
UserBalanceLogParam
} from '@/api/user/balance-log/model';
import {getPageTitle} from "@/utils/common";
import Extra from "@/views/user/index/components/extra.vue";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格列配置
const columns = ref<ColumnItem[]>([
// {
// key: 'index',
// width: 48,
// align: 'center',
// fixed: 'left',
// hideInSetting: true,
// customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
// },
{
title: '用户ID',
dataIndex: 'userId',
width: 80,
showSorterTooltip: false
},
{
title: '租户ID',
dataIndex: 'tenantId',
width: 90,
showSorterTooltip: false
},
{
title: '用户',
key: 'nickname',
dataIndex: 'nickname',
showSorterTooltip: false
},
{
title: '场景',
dataIndex: 'scene',
key: 'scene',
align: 'center',
showSorterTooltip: false,
filters: [
{ text: '用户充值', value: 10 },
{ text: '用户消费', value: 20 },
{ text: '管理员操作', value: 30 },
{ text: '订单退款', value: 40 }
]
},
{
title: '变动金额',
dataIndex: 'money',
key: 'money',
sorter: true,
showSorterTooltip: false
},
{
title: '账户金额',
dataIndex: 'balance',
key: 'balance',
sorter: true,
showSorterTooltip: false
},
{
title: '管理员备注',
dataIndex: 'remark'
},
{
title: '描述/说明',
dataIndex: 'comments'
},
{
title: '时间',
dataIndex: 'createTime',
sorter: true,
showSorterTooltip: false,
ellipsis: true,
customRender: ({ text }) => toDateString(text)
}
]);
// 表格选中数据
const selection = ref<UserBalanceLog[]>([]);
const searchText = ref('');
const userId = ref<number>(0);
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
// 默认搜索条件
const defaultWhere = reactive({
username: '',
nickname: '',
userId: undefined
});
// 表格数据源
const datasource: DatasourceFunction = ({
page,
limit,
where,
orders,
filters
}) => {
const [d1, d2] = dateRange.value ?? [];
where = {
...{
createTimeStart: d1 ? d1 + ' 00:00:00' : '',
createTimeEnd: d2 ? d2 + ' 23:59:59' : ''
}
};
if (userId.value) {
where.userId = userId.value;
}
if (filters) {
where.sceneMultiple = filters.scene;
}
where.keywords = searchText.value;
return pageUserBalanceLog({ ...where, ...orders, page, limit });
};
// 按用户搜索
const onSearch = (record) => {
userId.value = record?.userId;
searchText.value = record.nickname;
tableRef?.value?.reload();
};
const reset = () => {
userId.value = 0;
searchText.value = '';
reload();
};
/* 搜索 */
const reload = (where?: UserBalanceLogParam) => {
selection.value = [];
tableRef?.value?.reload({ page: 1, where });
};
/* 删除单个 */
const remove = (row: UserBalanceLog) => {
const hide = messageLoading('请求中..', 0);
removeUserBalanceLog(row.userId)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = messageLoading('请求中..', 0);
removeUserBalanceLogs(selection.value.map((d) => d.logId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
</script>
<script lang="ts">
export default {
name: 'SystemUser'
};
</script>