处理节假日列表

This commit is contained in:
2026-05-25 09:22:14 +08:00
parent 8ef911603e
commit 5c8204706e
13 changed files with 451 additions and 286 deletions

View File

@ -52,6 +52,7 @@ export interface EditUsernameParams {
// 验证码修改密码参数类型
export interface UpdatePwdByCaptchaParams {
mobile_area?: string
verify_type: number
code: string
login_password1: string

View File

@ -8,6 +8,7 @@ export interface UserInfo {
mobile: string
role_id: number
pass_admin: string
last_login?: string
salt_code_admin: string
real_check: number
par_uid: number

View File

@ -20,7 +20,7 @@
defineOptions({
name: 'Currency'
})
import FundDetailHeader from '@/components/common/header.vue'
import FundDetailHeader from '@/components/common/Header.vue'
import FundDetailTable from '@/components/common/Table.vue'
import { usePageLoading, useButtonLoading } from '@/composables/useLoading'
import FundDetailDialog from '@/components/common/Dialog.vue'
@ -46,8 +46,8 @@ interface HeaderButton {
const { loading, startLoading, stopLoading } = usePageLoading()
const { buttonLoading, startButtonLoading, stopButtonLoading } = useButtonLoading()
const buttonsOptions = ref(buttons)
const formItems = ref(form)
const buttonsOptions = ref<any>(buttons)
const formItems = ref<any>(form)
const tableData = ref([])
const tableColumnsOptions = ref(tableColumns)
const dialogTitle = ref('')
@ -79,7 +79,7 @@ const getTableList = async () => {
try {
startLoading()
const data = await getCurrencyList()
const data:any = await getCurrencyList()
tableData.value = (data || []).map((item: any) => {
return {

View File

@ -53,7 +53,7 @@ const getEnumDicOptions = async () => {
const res: any = await getEnumDicOptionsApi()
const typeIndex = searchOptions.value.findIndex((item: any) => item.prop === 'type')
if (typeIndex !== -1 && res) {
searchOptions.value[typeIndex].options = res.map((item: any) => ({
searchOptions.value[typeIndex]!.options = res.map((item: any) => ({
label: item.value,
value: item.id
}))

View File

@ -186,7 +186,7 @@ const tableRef = ref()
const handleSelectionChange = (rows: TableRow[]) => {
if (rows.length > 1) {
// 1
const lastRow = rows[rows.length - 1]
const lastRow:any = rows[rows.length - 1]
//
tableRef.value?.clearSelection()
//
@ -204,7 +204,7 @@ const handleApprove = async () => {
return
}
try {
await ElMessageBox.confirm(`是否确认通过该审核?订单号:${selectedRows.value[0].orderNo}`, '审核确认', {
await ElMessageBox.confirm(`是否确认通过该审核?订单号:${selectedRows.value[0]?.orderNo}`, '审核确认', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
@ -215,7 +215,7 @@ const handleApprove = async () => {
startLoading()
try {
await reviewRechargeOrder({ id: selectedRows.value[0].id, status: '3' })
await reviewRechargeOrder({ id: selectedRows.value[0]?.id, status: '3' })
await getList()
} finally {
stopLoading()
@ -229,7 +229,7 @@ const handleReject = async () => {
return
}
try {
await ElMessageBox.confirm(`是否确认驳回该审核?订单号:${selectedRows.value[0].orderNo}`, '审核确认', {
await ElMessageBox.confirm(`是否确认驳回该审核?订单号:${selectedRows.value[0]?.orderNo}`, '审核确认', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
@ -241,7 +241,7 @@ const handleReject = async () => {
//:1,2,3,4
startLoading()
try {
await reviewRechargeOrder({ id: selectedRows.value[0].id, status: '4' })
await reviewRechargeOrder({ id: selectedRows.value[0]?.id, status: '4' })
await getList()
} finally {
stopLoading()

View File

@ -149,7 +149,7 @@ const transferType = ref('internal')
/**
* @description 创建默认转账表单数据
*/
const createDefaultTransferForm = () => ({
const createDefaultTransferForm = ():any => ({
transferOutAccount: -1,
transferInAccount: '',
transferAmount: '',
@ -206,7 +206,7 @@ watch(
transferFormOptionsMap.value.transferInAccount =
transferFormOptionsMap.value.transferOutAccount.filter((item: any) => item.value !== val)
},
{ inmediate: true, deep: true },
{ immediate: true, deep: true },
)
const transferFormRules = ref(rules(transferForm.value))

View File

@ -59,7 +59,7 @@ const { loading, startLoading, stopLoading } = usePageLoading()
const total = ref(0)
const withdrawDialogVisible = ref(false)
const currentChannelId = ref<number>()
const currentChannelInfo = ref<{ id: number; name: string; currency?: string }>()
const currentChannelInfo = ref<any>()
const queryParams = reactive({
page: 1,

View File

@ -13,11 +13,11 @@ export const tableColumns = [
placeholder: '请选择入金货币',
},
// 接口地址
{ label: '接口地址', prop: 'api_url' },
// 接口appid
{ label: '接口appid', prop: 'api_appid' },
// 状态
{ label: '状态', prop: 'statusStr' },
// { label: '接口地址', prop: 'api_url' },
// // 接口appid
// { label: '接口appid', prop: 'api_appid' },
// // 状态
// { label: '状态', prop: 'statusStr' },
// 操作
{ label: '操作', prop: 'action', width: 100, slotName: 'action' as const },
]

View File

@ -64,7 +64,7 @@ type ChannelType = {
channel_code: string
}
const getStatusText = (status: number | string) => {
const getStatusText = (status: any) => {
return ['', '正常', '禁用'][status]
}
@ -73,7 +73,7 @@ const { loading, startLoading, stopLoading } = usePageLoading()
const { buttonLoading: submitLoading, startButtonLoading: startSubmitLoading, stopButtonLoading: stopSubmitLoading } = useButtonLoading()
const initData = async () => {
startLoading()
const res = await getChannelWithdrawList()
const res:any = await getChannelWithdrawList()
stopLoading()
console.log(res)
tableData.value = res.map((item: ChannelType) => ({
@ -84,13 +84,13 @@ const initData = async () => {
}
//
const tableColumnsOptions = ref(tableColumns)
const tableData = ref([])
const tableColumnsOptions = ref<any>(tableColumns)
const tableData = ref<any>([])
const tableRef = ref()
const dialogVisible = ref(false)
const dialogTitleType = ref(1)
const formData = ref({
const formData = ref<any>({
name: '',
channel_fee: null,
currency_id: null,
@ -100,7 +100,7 @@ const formData = ref({
channel_code: '',
status: 1,
})
const formItems = ref(formItemsData)
const formItems = ref<any>(formItemsData)
const formRules = ref(formRulesData)
const optionsMap = ref(optionsMapData)
const submitDetail = async () => {
@ -180,7 +180,7 @@ const clearSelection = () => {
onMounted(() => {
initData()
//
getChannelList().then((data) => {
getChannelList().then((data:any) => {
console.log(data)
optionsMap.value.currency_id = (data || []).map((item: any) => ({
value: item.id,

View File

@ -40,7 +40,7 @@
<el-icon :size="32"><UserFilled /></el-icon>
</div>
<div class="user-details">
<span class="user-name">{{ userStore.userInfo.username }}</span>
<span class="user-name">{{ userStore.userInfo?.username || '-' }}</span>
<!-- <el-tag size="small" :type="+userStore.userInfo.role_id === 1 ? 'danger' : 'primary'">
{{ userStore.userInfo.role }}
</el-tag> -->
@ -48,11 +48,11 @@
</div>
<div class="info-row">
<span class="info-label">用户ID</span>
<span class="info-value">{{ userStore.userInfo.id }}</span>
<span class="info-value">{{ userStore.userInfo?.id || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">最后登录</span>
<span class="info-value">{{ userStore.userInfo.last_login }}</span>
<span class="info-value">{{ userStore.userInfo?.last_login || '-' }}</span>
</div>
</div>
</div>
@ -197,7 +197,9 @@ onMounted(() => {
<style scoped lang="scss">
.dashboard {
padding: 24px;
padding: 20px;
max-width: 1600px;
margin: 0 auto;
}
.page-header {
@ -209,7 +211,7 @@ onMounted(() => {
border-bottom: 1px solid var(--el-border-color-light);
h1 {
font-size: 20px;
font-size: 22px;
font-weight: 600;
color: var(--el-text-color-primary);
margin: 0;
@ -227,32 +229,45 @@ onMounted(() => {
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 16px;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
@media (max-width: 1200px) {
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 900px) {
grid-template-columns: repeat(2, 1fr);
}
@media (max-width: 600px) {
grid-template-columns: 1fr;
}
}
.stat-box {
display: flex;
align-items: center;
gap: 16px;
padding: 20px;
padding: 20px 24px;
background: #fff;
border-radius: 12px;
border: 1px solid var(--el-border-color-lighter);
transition: all 0.2s ease;
transition: all 0.25s ease;
&:hover {
border-color: var(--el-color-primary-light-5);
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
transform: translateY(-2px);
}
&__icon {
width: 48px;
height: 48px;
width: 52px;
height: 52px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
border-radius: 12px;
flex-shrink: 0;
}
@ -264,8 +279,8 @@ onMounted(() => {
}
&__value {
font-size: 20px;
font-weight: 600;
font-size: 24px;
font-weight: 700;
color: var(--el-text-color-primary);
line-height: 1.2;
max-width: 100%;
@ -275,24 +290,28 @@ onMounted(() => {
}
&__label {
font-size: 13px;
font-size: 14px;
color: var(--el-text-color-secondary);
margin-top: 4px;
margin-top: 6px;
}
}
.stat-box--0 .stat-box__icon { background: #ecf5ff; color: #409eff; }
.stat-box--1 .stat-box__icon { background: #f0f9eb; color: #67c23a; }
.stat-box--2 .stat-box__icon { background: #fdf6ec; color: #e6a23c; }
.stat-box--3 .stat-box__icon { background: #fef0f0; color: #f56c6c; }
.stat-box--4 .stat-box__icon { background: #f4f4f5; color: #909399; }
.stat-box--5 .stat-box__icon { background: #fdf5f6; color: #c71585; }
.stat-box--6 .stat-box__icon { background: #f0f9ff; color: #0089e5; }
.stat-box--0 .stat-box__icon { background: linear-gradient(135deg, #ecf5ff, #d9ecff); color: #409eff; }
.stat-box--1 .stat-box__icon { background: linear-gradient(135deg, #f0f9eb, #e1f3d8); color: #67c23a; }
.stat-box--2 .stat-box__icon { background: linear-gradient(135deg, #fdf6ec, #fbeccb); color: #e6a23c; }
.stat-box--3 .stat-box__icon { background: linear-gradient(135deg, #fef0f0, #fad7d7); color: #f56c6c; }
.stat-box--4 .stat-box__icon { background: linear-gradient(135deg, #f4f4f5, #e4e4e7); color: #909399; }
.stat-box--5 .stat-box__icon { background: linear-gradient(135deg, #fdf5f6, #f9d7e3); color: #c71585; }
.stat-box--6 .stat-box__icon { background: linear-gradient(135deg, #f0f9ff, #d6ecff); color: #0089e5; }
.content-area {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 16px;
grid-template-columns: 1fr 1fr;
gap: 20px;
@media (max-width: 768px) {
grid-template-columns: 1fr;
}
}
.info-panel {
@ -305,12 +324,12 @@ onMounted(() => {
.panel-header {
display: flex;
align-items: center;
gap: 8px;
padding: 14px 16px;
gap: 10px;
padding: 16px 20px;
background: var(--el-fill-color-light);
border-bottom: 1px solid var(--el-border-color-lighter);
font-size: 14px;
font-weight: 500;
font-size: 15px;
font-weight: 600;
color: var(--el-text-color-primary);
.el-icon {
@ -319,24 +338,24 @@ onMounted(() => {
}
.panel-content {
padding: 16px;
padding: 20px;
}
.user-info {
display: flex;
align-items: center;
gap: 14px;
padding-bottom: 14px;
margin-bottom: 14px;
gap: 16px;
padding-bottom: 16px;
margin-bottom: 16px;
border-bottom: 1px dashed var(--el-border-color-lighter);
.user-avatar {
width: 48px;
height: 48px;
width: 52px;
height: 52px;
display: flex;
align-items: center;
justify-content: center;
background: var(--el-color-primary-light-9);
background: linear-gradient(135deg, var(--el-color-primary-light-9), var(--el-color-primary-light-7));
border-radius: 50%;
color: var(--el-color-primary);
}
@ -347,7 +366,7 @@ onMounted(() => {
gap: 6px;
.user-name {
font-size: 15px;
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
}
@ -358,7 +377,7 @@ onMounted(() => {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
padding: 12px 0;
border-bottom: 1px dashed var(--el-border-color-lighter);
&:last-child {
@ -366,13 +385,13 @@ onMounted(() => {
}
.info-label {
font-size: 13px;
font-size: 14px;
color: var(--el-text-color-secondary);
}
.info-value {
font-size: 13px;
font-weight: 500;
font-size: 14px;
font-weight: 600;
color: var(--el-text-color-primary);
}
}
@ -380,17 +399,17 @@ onMounted(() => {
.action-list {
display: flex;
flex-direction: column;
gap: 8px;
gap: 10px;
}
.action-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
gap: 12px;
padding: 12px 14px;
background: var(--el-fill-color-light);
border-radius: 8px;
font-size: 13px;
border-radius: 10px;
font-size: 14px;
color: var(--el-text-color-regular);
cursor: pointer;
transition: all 0.2s ease;
@ -399,6 +418,10 @@ onMounted(() => {
&:hover {
background: var(--el-color-primary-light-9);
color: var(--el-color-primary);
.arrow {
opacity: 1;
}
}
.el-icon {
@ -409,7 +432,8 @@ onMounted(() => {
.arrow {
margin-left: auto;
font-size: 12px;
opacity: 0.5;
opacity: 0.4;
transition: opacity 0.2s ease;
}
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="personal-center table_form-container">
<div class="personal-center table_form-container" v-loading="loading">
<div class="page-header">
<h2>{{ t('personalCenter.pageTitle') }}</h2>
</div>
@ -174,7 +174,9 @@ import {
updatePwdByCaptchaApi
} from '@/api/modules/profile/personalCenter';
import { useButtonLoading } from '@/composables/useLoading';
import { useButtonLoading, usePageLoading } from '@/composables/useLoading';
const { loading, startLoading, stopLoading } = usePageLoading(true);
const userInfo = reactive<UserInfo>({
id: 0,
@ -290,6 +292,7 @@ const passwordFormRules = ref<FormRules>({
//
const fetchUserProfile = async () => {
startLoading();
try {
const res = await getUserInfoApi();
Object.assign(userInfo, res);
@ -297,6 +300,8 @@ const fetchUserProfile = async () => {
} catch (error) {
ElMessage.error(t('personalCenter.getUserInfoFailed'));
console.error('获取用户信息失败:', error);
} finally {
stopLoading();
}
};

View File

@ -1,243 +1,377 @@
<template>
<div class="trade-group table_form-container">
<el-form-item label="交易节假日时间设置">
<el-button style="margin-left: 18px" type="primary" v-auth="'contractVariety_addHoliday'"
@click="handleAdd">添加</el-button>
<el-button style="margin-left: 18px" type="danger" v-auth="'contractVariety_addHoliday'"
@click="handleDel">删除</el-button>
</el-form-item>
<!-- 表格 -->
<div class="table-box">
<table v-loading="loading">
<thead>
<tr>
<th>名称</th>
<th>休市时间</th>
<th>休市市场</th>
<th>备注</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in dataList" :key="`${item.id}-${index}`">
<td>
<el-input v-if="item.editStatus" v-model="item.name" style="width: 80px" />
<span v-else>{{ item.name }}</span>
</td>
<td>
<el-date-picker v-if="item.editStatus" v-model="item.datePicker" type="datetimerange"
start-placeholder="休市开始时间" end-placeholder="休市结束时间" format="YYYY-MM-DD HH:mm:ss"
date-format="YYYY-MM-DD HH:mm:ss" time-format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" />
<span v-else>{{ item.datePicker[0] }} - {{ item.datePicker[1] }}</span>
</td>
<td>
<el-select multiple placeholder="请选择休市市场" style="width: 240px" v-model="item.groupId"
v-if="item.editStatus">
<el-option v-for="item in marketList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<span>{{
(item?.groupId || [])
.map(
(item: any) =>
(marketList || []).find((item2: any) => item2.value === item)?.label || '',
)
.join(',')
}}</span>
</td>
<td>
<el-input v-if="item.editStatus" style="width: 250px" v-model="item.description" />
<span v-else>{{ item.description }}</span>
</td>
<td>
<el-button type="primary" v-if="!item.editStatus" @click="item.editStatus = true"
v-auth="'contractVariety_addHoliday'">编辑</el-button>
<el-button type="danger" v-if="!item.editStatus" @click="handleDel(item.id, index)"
v-auth="'contractVariety_addHoliday'">删除</el-button>
<el-button type="primary" v-if="item.editStatus" @click="submitItem(index)"
v-auth="'contractVariety_addHoliday'">确认</el-button>
<el-button type="danger" v-if="item.editStatus" @click="item.editStatus = false"
v-auth="'contractVariety_addHoliday'">取消</el-button>
</td>
</tr>
</tbody>
</table>
<div class="holidays-container table_form-container">
<!-- 搜索区域 -->
<div class="search-container">
<el-form inline :model="searchForm">
<el-form-item label="节假日名称">
<el-input v-model="searchForm.name" placeholder="请输入节假日名称" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch" v-auth="'contractVariety_addHoliday'">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<div class="search-right">
<el-button type="primary" @click="handleAdd" v-auth="'contractVariety_addHoliday'">添加节假日</el-button>
</div>
</div>
<!-- 列表区域使用公共 Table 组件 -->
<Table
ref="tableRef"
:table-data="tableData"
:columns="tableColumns"
row-key="id"
:loading="loading"
>
<!-- 操作列插槽 -->
<template #action="{ row }">
<el-button type="primary" size="small" @click="handleEdit(row)" v-auth="'contractVariety_addHoliday'">编辑</el-button>
<el-button type="danger" size="small" @click="handleDel(row)" v-auth="'contractVariety_addHoliday'">删除</el-button>
</template>
</Table>
<!-- 新增/编辑弹窗 -->
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="600px"
:destroy-on-close="true"
@close="handleDialogClose"
>
<Form
ref="formRef"
:form-data="formData"
:form-rules="formRules"
:form-items="formItems"
:options-map="optionsMap"
>
<!-- 休市市场多选插槽 -->
<template #marketSelect>
<el-select
v-model="formData.groupId"
multiple
placeholder="请选择休市市场"
style="width: 100%"
clearable
>
<el-option
v-for="market in marketList"
:key="market.value"
:label="market.label"
:value="market.value"
/>
</el-select>
</template>
</Form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { getGroupListApi } from '@/api/modules/trade/group'
import { getHolidayList, addHoliday, editHoliday, delHoliday } from '@/api/modules/trade/time'
import { ElMessage, ElMessageBox } from 'element-plus'
import { usePageLoading } from '@/composables/useLoading'
import Table from '@/components/common/Table.vue'
import Form from '@/components/common/Form.vue'
defineOptions({
name: 'Holidays'
})
import { ref, onMounted } from 'vue'
import { getGroupListApi } from '@/api/modules/trade/group'
import { getHolidayList, addHoliday, editHoliday, delHoliday } from '@/api/modules/trade/time'
import { ElMessageBox } from 'element-plus'
import { usePageLoading } from '@/composables/useLoading'
//
interface HolidayItem {
id: string
name: string
start_time: string
end_time: string
group_id: string[]
description: string
}
interface TableRow {
id: string
name: string
startTime: string
endTime: string
marketNames: string
groupId: string[]
description: string
}
// loading
const { loading, startLoading, stopLoading } = usePageLoading()
const submitLoading = ref(false)
type DataItem = {
id?: number | string
name: string
start_time?: string
end_time?: string
datePicker: string[]
groupId: number[]
description: string
editStatus: boolean
//
const marketList = ref<{ label: string; value: string }[]>([])
//
const tableColumns = [
{ prop: 'name', label: '节假日名称', width: 150 },
{ prop: 'startTime', label: '休市开始时间', width: 180 },
{ prop: 'endTime', label: '休市结束时间', width: 180 },
{ prop: 'marketNames', label: '休市市场', width: 200 },
{ prop: 'description', label: '备注' },
{ prop: 'action', label: '操作', width: 180, slotName: 'action' },
]
//
const tableData = ref<TableRow[]>([])
const tableRef = ref()
//
const searchForm = reactive({
name: '',
})
//
const dialogVisible = ref(false)
const dialogTitle = computed(() => (isEdit.value ? '编辑节假日' : '添加节假日'))
const isEdit = ref(false)
const currentId = ref<string | null>(null)
//
const formData = reactive({
name: '',
datePicker: [] as string[],
groupId: [] as string[],
description: '',
})
//
const formRules = {
name: [{ required: true, message: '请输入节假日名称', trigger: 'blur' }],
datePicker: [{ required: true, message: '请选择休市时间', trigger: 'change' }],
groupId: [{ required: true, message: '请选择休市市场', trigger: 'blur' }],
description: [{ required: true, message: '请输入备注', trigger: 'change' }],
}
const dataList = ref<DataItem[]>([])
//
const formItems: Array<{
type: 'input' | 'date' | 'slot' | 'textarea'
label: string
prop: string
placeholder?: string
required?: boolean
dateType?: 'datetimerange'
rangeSeparator?: string
startPlaceholder?: string
endPlaceholder?: string
valueFormat?: string
slotName?: string
}> = [
{ type: 'input', label: '节假日名称', prop: 'name', placeholder: '请输入节假日名称', required: true },
{
type: 'date',
label: '休市时间',
prop: 'datePicker',
dateType: 'datetimerange',
rangeSeparator: '至',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
valueFormat: 'YYYY-MM-DD HH:mm:ss',
required: true,
},
{ type: 'slot', label: '休市市场', prop: 'groupId', slotName: 'marketSelect' },
{ type: 'textarea', label: '备注', prop: 'description', placeholder: '请输入备注' },
]
const marketList = ref<{ label: string; value: number | string }[]>([])
// Map slot 使
const optionsMap = computed(() => ({}))
//
const formRef = ref()
/**
* @description: 获取市场列表
*/
const getMarketList = async () => {
getGroupListApi().then((res) => {
console.log(res)
marketList.value = res.map((item: { name: string; id: number }[]) => ({
label: item.name,
value: item.id + '',
}))
})
}
const initDate = () => {
startLoading()
try {
getHolidayList().then((res) => {
dataList.value = res.map((item: any) => ({
id: item.id + '',
name: item.name,
start_time: item.start_time,
end_time: item.end_time,
datePicker: [item.start_time, item.end_time],
groupId: item.group_id,
description: item.description,
editStatus: false,
}))
})
} finally { stopLoading() }
}
const handleAdd = () => {
dataList.value.unshift({
name: '',
start_time: '',
end_time: '',
datePicker: [],
groupId: [],
description: '',
editStatus: true,
})
}
const submitItem = (idx: number) => {
const submitObj = {
name: dataList.value[idx]!.name,
start_time: dataList.value[idx]!.datePicker[0],
end_time: dataList.value[idx]!.datePicker[1],
group_id: dataList.value[idx]!.groupId.join(','),
description: dataList.value[idx]!.description,
}
if (dataList.value[idx]!.id) {
editHoliday({ id: dataList.value[idx]!.id, ...submitObj }).then(() => {
initDate()
})
} else {
addHoliday(submitObj).then(() => {
initDate()
})
}
}
const handleDel = (id: number | string, idx: number) => {
if (!id) {
dataList.value.splice(idx, 1)
return
}
ElMessageBox.confirm('确认删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
}).then(() => {
delHoliday({ id }).then(() => {
initDate()
})
})
const res = await getGroupListApi()
console.log('res:', res);
marketList.value = res.map((item: { name: string; id: number }) => ({
label: item.name,
value: String(item.id),
}))
console.log('marketList.value:', marketList.value);
}
/**
* @description: 页面加载完成需要请求的数据
* @description: 获取节假日列表
*/
onMounted(() => {
getMarketList()
initDate()
const getList = async () => {
startLoading()
try {
const res = await getHolidayList()
//
const filteredData = res.filter((item: HolidayItem) => {
if (searchForm.name && !item.name.includes(searchForm.name)) {
return false
}
return true
})
tableData.value = filteredData.map((item: HolidayItem) => {
const groupIds = item.group_id ? String(item.group_id).split(',').filter(Boolean) : []
const marketNames = groupIds
.map((id) => marketList.value.find((m) => m.value === id)?.label || '')
.filter(Boolean)
.join(',')
return {
id: String(item.id),
name: item.name,
startTime: item.start_time,
endTime: item.end_time,
marketNames,
groupId: groupIds,
description: item.description,
}
})
} finally {
stopLoading()
}
}
/**
* @description: 搜索
*/
const handleSearch = async () => {
await getList()
}
/**
* @description: 重置
*/
const handleReset = () => {
searchForm.name = ''
getList()
}
/**
* @description: 打开添加弹窗
*/
const handleAdd = () => {
isEdit.value = false
currentId.value = null
resetForm()
dialogVisible.value = true
}
/**
* @description: 打开编辑弹窗
*/
const handleEdit = (row: TableRow) => {
isEdit.value = true
currentId.value = row.id
formData.name = row.name
formData.datePicker = [row.startTime, row.endTime]
// 使 groupId
formData.groupId = row.groupId
formData.description = row.description
dialogVisible.value = true
}
/**
* @description: 删除
*/
const handleDel = async (row: TableRow) => {
try {
await ElMessageBox.confirm('确认删除该节假日吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
await delHoliday({ id: row.id })
ElMessage.success('删除成功')
await getList()
} catch {
//
}
}
/**
* @description: 重置表单
*/
const resetForm = () => {
formData.name = ''
formData.datePicker = []
formData.groupId = []
formData.description = ''
}
/**
* @description: 弹窗关闭
*/
const handleDialogClose = () => {
resetForm()
formRef.value?.resetFields()
}
/**
* @description: 提交表单
*/
const handleSubmit = async () => {
try {
await formRef.value?.validate()
} catch {
return
}
submitLoading.value = true
try {
const submitData = {
name: formData.name,
start_time: formData.datePicker[0],
end_time: formData.datePicker[1],
group_id: formData.groupId.join(','),
description: formData.description,
}
if (isEdit.value && currentId.value) {
await editHoliday({ id: currentId.value, ...submitData })
ElMessage.success('编辑成功')
} else {
await addHoliday(submitData)
ElMessage.success('添加成功')
}
dialogVisible.value = false
await getList()
} finally {
submitLoading.value = false
}
}
/**
* @description: 页面初始化
*/
onMounted(async () => {
await getMarketList()
await getList()
})
</script>
<style scoped lang="scss">
.trade-group {
overflow-y: scroll;
}
.holidays-container {
:deep(.search-container) {
display: flex;
justify-content: space-between;
align-items: flex-start;
flex-wrap: wrap;
gap: 16px;
/* 给 table 及所有 td 加边框 */
table {
border-collapse: collapse;
width: 100%;
table-layout: auto;
/* 宽度自适应内容 */
th {
font-weight: bold;
}
td,
th {
height: 48px;
border: 1px solid #dcdfe6;
padding: 4px 8px;
/* 内边距缩小 */
text-align: center;
font-size: 12px;
/* 文字变小 */
white-space: nowrap;
/* 文字不换行 */
vertical-align: middle;
/* 垂直居中 */
/* 时间选择器容器:两个选择器横排不换行 */
:deep(.el-time-picker) {
display: inline-block;
.el-range-editor {
width: 100px;
/* 缩小时间选择器宽度 */
font-size: 12px;
}
.el-range-input {
font-size: 12px;
}
.el-form {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
/* input 输入框也缩小 */
:deep(.el-input) {
width: 60px;
.el-input__inner {
font-size: 12px;
height: 28px;
}
}
/* 按钮缩小 */
:deep(.el-button) {
padding: 5px 10px;
font-size: 12px;
.search-right {
flex-shrink: 0;
}
}
}

View File

@ -148,7 +148,7 @@ const activeTab = ref<string>('email')
//
const registerFormRef = ref<FormInstance>()
const registerForm = ref({
const registerForm = ref<any>({
email: '',
countryCode: '+86',
phone: '',