feat:移植工程
This commit is contained in:
181
src/views/admin/account/index.vue
Normal file
181
src/views/admin/account/index.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
<div class="button-container">
|
||||
<el-button type="primary" @click="addClick">新增账号</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="accountInfo.accountList"
|
||||
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="username" label="用户姓名" align="center" min-width="20%"/>
|
||||
<el-table-column prop="accountName" label="账号名称" align="center" min-width="20%"/>
|
||||
<el-table-column prop="date" label="创建日期" align="center" min-width="20%"/>
|
||||
<el-table-column label="账号状态" align="center" min-width="20%">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.state === 0" type="primary">正常</el-tag>
|
||||
<el-tag v-else-if="scope.row.state === 1" type="warning">禁用</el-tag>
|
||||
<el-tag v-else-if="scope.row.state === 2" type="danger">注销</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" align="center" width="280">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="resetClick(scope.row)">重置密码</el-button>
|
||||
<el-button type="primary" @click="disableClick(scope.row)">禁用</el-button>
|
||||
<el-button type="danger" @click="deleteClick(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog v-model="accountInfo.accountDialog.visible"
|
||||
:title="accountInfo.accountDialog.title"
|
||||
center width="500" @open="openDialogEvent">
|
||||
<el-form ref="formRef" :model="accountInfo.accountDialog.data"
|
||||
:rules="rules" label-width="100px">
|
||||
<el-form-item label="账号名称" prop="accountName">
|
||||
<el-input v-model="accountInfo.accountDialog.data.accountName" autocomplete="off"
|
||||
placeholder="请输入账号名称(登录账号)"
|
||||
:maxlength="10" show-word-limit clearable/>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户姓名" prop="username">
|
||||
<el-input v-model="accountInfo.accountDialog.data.username" autocomplete="off"
|
||||
placeholder="请输入用户姓名"
|
||||
:maxlength="10" show-word-limit clearable/>
|
||||
</el-form-item>
|
||||
<el-form-item label="账号密码" prop="password">
|
||||
<el-input v-model="accountInfo.accountDialog.data.password" autocomplete="off"
|
||||
placeholder="请输入密码" clearable show-password/>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认密码" prop="confirmPassword">
|
||||
<el-input v-model="accountInfo.accountDialog.data.confirmPassword" autocomplete="off"
|
||||
placeholder="请再次输入密码" clearable show-password/>
|
||||
</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 { commonElMessageBox, tableCellStyle, tableHeaderStyle, tableRowStyle } from 'vue3-common/utils/elUtil'
|
||||
import { IAccount } from '@/types/auth.ts'
|
||||
import { ElMessage, FormRules } from 'element-plus'
|
||||
import type { IDialog, IHandleApi } from 'vue3-common/types'
|
||||
import { accountRules } from '@/utils/element/elRules.ts'
|
||||
import { deleteAccountApi, queryAccountApi, registerAccountApi } from '@/apis/account.ts'
|
||||
const formRef = ref()
|
||||
const rules = reactive<FormRules>(accountRules)
|
||||
|
||||
const accountInfo = reactive({
|
||||
accountList: [] as IAccount[],
|
||||
setAccountType: 'ADD' as IHandleApi,
|
||||
accountDialog: {
|
||||
title: '',
|
||||
visible: false,
|
||||
data: {}
|
||||
} as IDialog<IAccount>
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
accountInfo.accountList = await queryAccountApi()
|
||||
})
|
||||
|
||||
const addClick = () => {
|
||||
accountInfo.setAccountType = 'ADD'
|
||||
accountInfo.accountDialog = {
|
||||
title: '新增账号',
|
||||
visible: true,
|
||||
data: {
|
||||
accountName: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
username: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击编辑按钮
|
||||
* @param account 账户
|
||||
*/
|
||||
const resetClick = async (account: IAccount) => {
|
||||
|
||||
}
|
||||
|
||||
const disableClick = (account: IAccount) => {
|
||||
ElMessage.info('该功能暂未开发')
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击删除按钮
|
||||
* @param account 账户
|
||||
*/
|
||||
const deleteClick = (account: IAccount) => {
|
||||
commonElMessageBox(`请确认删除该账号:${account.accountName} ?`).then(() => {
|
||||
accountInfo.setAccountType = 'DELETE'
|
||||
setAccountApi(account.id)
|
||||
})
|
||||
}
|
||||
|
||||
const openDialogEvent = () => {
|
||||
nextTick(() => {
|
||||
formRef.value.clearValidate()
|
||||
})
|
||||
}
|
||||
|
||||
const setAccountApi = async (id?: number) => {
|
||||
switch (accountInfo.setAccountType) {
|
||||
case 'ADD':
|
||||
if (checkPassword()) {
|
||||
await registerAccountApi(accountInfo.accountDialog.data)
|
||||
ElMessage.success('新增账号成功')
|
||||
}
|
||||
break
|
||||
case 'DELETE':
|
||||
await deleteAccountApi(id)
|
||||
ElMessage.success('删除账号成功')
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
accountInfo.accountList = await queryAccountApi()
|
||||
accountInfo.accountDialog.visible = false
|
||||
}
|
||||
|
||||
const checkPassword = () => {
|
||||
const { password, confirmPassword } = accountInfo.accountDialog.data
|
||||
if (password !== confirmPassword) {
|
||||
ElMessage.error('请确认两次密码是否一致')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const cancelClick = () => {
|
||||
accountInfo.accountDialog.visible = false
|
||||
}
|
||||
|
||||
const confirmClick = async () => {
|
||||
await formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
if (accountInfo.setAccountType === 'ADD') {
|
||||
if (checkPassword()) {
|
||||
await setAccountApi(accountInfo.accountDialog.data.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
166
src/views/admin/bill/book.vue
Normal file
166
src/views/admin/bill/book.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
<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: 50%"
|
||||
class="card-item">
|
||||
<el-table-column type="index" align="center" width="50" />
|
||||
<el-table-column prop="name" label="名称" align="center" min-width="10%"/>
|
||||
<el-table-column label="图标" align="center" min-width="10%">
|
||||
<template #default="scope">
|
||||
<i :class="scope.row.icon" :style="{color: scope.row.color, fontSize: '24px'}"></i>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="editBookClick(scope.row)">编辑</el-button>
|
||||
<el-button type="danger" @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="500" @open="openDialogEvent">
|
||||
<el-form ref="formRef" :model="billInfo.billBookDialog.data"
|
||||
:rules="rules" 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'
|
||||
import { ElMessage, FormRules } from 'element-plus'
|
||||
import { IBillBook } from '@/types/bill'
|
||||
import { billBookRules } from '@/utils/element/elRules'
|
||||
import { deepCopyObject } from 'vue3-common/utils/dataUtil'
|
||||
import type { IDialog, IHandleApi } from 'vue3-common/types'
|
||||
import { addBillBookApi, updateBillBookApi } from '@/apis/bill'
|
||||
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>
|
||||
223
src/views/admin/bill/category.vue
Normal file
223
src/views/admin/bill/category.vue
Normal file
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
<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" min-width="10%"/>
|
||||
<el-table-column prop="bookName" label="账本" align="center" min-width="10%"/>
|
||||
<el-table-column label="类型" align="center" min-width="10%">
|
||||
<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" min-width="10%">
|
||||
<template #default="scope">
|
||||
<i :class="scope.row.icon" :style="{color: scope.row.color, fontSize: '24px'}"></i>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="editCategoryClick(scope.row)">编辑</el-button>
|
||||
<el-button type="danger" @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="500" @open="openDialogEvent">
|
||||
<el-form ref="formRef" :model="billInfo.billCategoryDialog.data"
|
||||
:rules="rules" 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'
|
||||
import { IBillBook, IBillCategory } from '@/types/bill'
|
||||
import { ElMessage, FormRules } from 'element-plus'
|
||||
import { billCategoryRules } from '@/utils/element/elRules'
|
||||
import { addBillCategoryApi, updateBillCategoryApi } from '@/apis/bill'
|
||||
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>
|
||||
166
src/views/admin/bill/pay.vue
Normal file
166
src/views/admin/bill/pay.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
<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: 50%"
|
||||
class="card-item">
|
||||
<el-table-column type="index" align="center" width="50" />
|
||||
<el-table-column prop="name" label="名称" align="center" min-width="10%"/>
|
||||
<el-table-column label="图标" align="center" min-width="10%">
|
||||
<template #default="scope">
|
||||
<i :class="scope.row.icon" :style="{color: scope.row.color, fontSize: '24px'}"></i>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column fixed="right" label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="editPayClick(scope.row)">编辑</el-button>
|
||||
<el-button type="danger" @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="500" @open="openDialogEvent">
|
||||
<el-form ref="formRef" :model="billInfo.billPayDialog.data"
|
||||
:rules="rules" 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'
|
||||
import { ElMessage, FormRules } from 'element-plus'
|
||||
import { IBillPay } from '@/types/bill'
|
||||
import { billPayRules } from '@/utils/element/elRules'
|
||||
import { deepCopyObject } from 'vue3-common/utils/dataUtil'
|
||||
import { addBillPayApi, updateBillPayApi } from '@/apis/bill'
|
||||
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>
|
||||
100
src/views/admin/blog/article.vue
Normal file
100
src/views/admin/blog/article.vue
Normal file
@@ -0,0 +1,100 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
<div class="button-container">
|
||||
<el-button type="primary" @click="addNewBlogClick">新增文章</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="blogStore.blogList"
|
||||
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="title" label="标题" align="center" min-width="10%"/>
|
||||
<el-table-column prop="category" label="类别" align="center" min-width="10%" />
|
||||
<el-table-column label="精品" align="center" min-width="10%">
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.isGreat">是</el-tag>
|
||||
<el-tag type="danger" v-else>否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="置顶" align="center" min-width="10%">
|
||||
<template #default="scope">
|
||||
<el-tag type="success" v-if="scope.row.topValue > 1">是</el-tag>
|
||||
<el-tag type="danger" v-else>否</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="wordCount" label="字数" align="center" min-width="10%" />
|
||||
<el-table-column prop="visitCount" label="阅读次数" align="center" min-width="10%" />
|
||||
<el-table-column fixed="right" label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="editBlogClick(scope.row)">编辑</el-button>
|
||||
<el-button type="danger" @click="deleteBlogClick(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:current-page="blogStore.adminPageInfo.currentPage"
|
||||
:page-size="blogStore.adminPageInfo.pageSize"
|
||||
:total="blogStore.adminPageInfo.totalSize"
|
||||
layout="total, prev, pager, next"
|
||||
@change="changePageClick"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue'
|
||||
import { useBlogStore } from '@/store/blog.ts'
|
||||
import { IBlog } from '@/types/blog.ts'
|
||||
import { commonElMessageBox, tableCellStyle, tableHeaderStyle, tableRowStyle } from 'vue3-common/utils/elUtil'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const blogStore = useBlogStore()
|
||||
|
||||
onMounted(async () => {
|
||||
await blogStore.queryAdminBlog()
|
||||
})
|
||||
|
||||
/**
|
||||
* 点击切换博客页数按钮
|
||||
* @param page 页码
|
||||
* @param pageSize 每页大小
|
||||
*/
|
||||
const changePageClick = async (page: number, pageSize: number) => {
|
||||
blogStore.adminPageInfo.currentPage = page
|
||||
blogStore.adminPageInfo.pageSize = pageSize
|
||||
await blogStore.queryAdminBlog()
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击新增博客按钮
|
||||
*/
|
||||
const addNewBlogClick = () => {
|
||||
router.push({ name: 'AdminBlogDetailId', params: { id: 0 } })
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击编辑博客按钮
|
||||
* @param blog 博客
|
||||
*/
|
||||
const editBlogClick = async (blog: IBlog) => {
|
||||
await router.push({ name: 'AdminBlogDetailId', params: { id: blog.id } })
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击删除博客按钮
|
||||
* @param blog 博客
|
||||
*/
|
||||
const deleteBlogClick = (blog: IBlog) => {
|
||||
blogStore.blogApiType = 'DELETE'
|
||||
|
||||
commonElMessageBox('是否确认删除该博客?').then(() => {
|
||||
blogStore.handleBlogApi(blog.id)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
82
src/views/admin/blog/category.vue
Normal file
82
src/views/admin/blog/category.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
<div class="button-container">
|
||||
<el-button type="primary" @click="addNewCategoryClick">新增类别</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="blogStore.blogCategoryList"
|
||||
border stripe
|
||||
:header-cell-style="tableHeaderStyle()"
|
||||
:cell-style="tableCellStyle()"
|
||||
:row-style="tableRowStyle()"
|
||||
style="width: 50%"
|
||||
class="card-item">
|
||||
<el-table-column type="index" align="center" width="50" />
|
||||
<el-table-column prop="name" label="名称" align="center" min-width="10%"/>
|
||||
<el-table-column prop="count" label="数量" align="center" min-width="10%" />
|
||||
<el-table-column fixed="right" label="操作" align="center" width="200">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="editCategoryClick(scope.row)">编辑</el-button>
|
||||
<el-button type="danger" @click="deleteCategoryClick(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue'
|
||||
import { useBlogStore } from '@/store/blog.ts'
|
||||
import { IBlogCategory } from '@/types/blog.ts'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { tableCellStyle, tableHeaderStyle, tableRowStyle } from 'vue3-common/utils/elUtil'
|
||||
|
||||
const blogStore = useBlogStore()
|
||||
|
||||
onMounted(async () => {
|
||||
await blogStore.queryBlogCategory()
|
||||
})
|
||||
|
||||
/**
|
||||
* 点击新增类别按钮
|
||||
*/
|
||||
const addNewCategoryClick = () => {
|
||||
ElMessageBox.prompt('请输入类别名称', '新增类别', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
inputPlaceholder: '请输入类别名称',
|
||||
inputPattern: /^.{0,10}$/,
|
||||
inputErrorMessage: '请输入10字以内的类别名称'
|
||||
})
|
||||
.then(({ value }) => {
|
||||
console.log(value)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击编辑类别按钮
|
||||
* @param category 类别
|
||||
*/
|
||||
const editCategoryClick = async (category: IBlogCategory) => {
|
||||
ElMessageBox.prompt('请输入类别名称', '编辑类别', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
inputValue: category.name,
|
||||
inputPlaceholder: '请输入类别名称',
|
||||
inputPattern: /^.{0,10}$/,
|
||||
inputErrorMessage: '请输入10字以内的类别名称'
|
||||
})
|
||||
.then(({ value }) => {
|
||||
console.log(value)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击删除类别按钮
|
||||
* @param category 类别
|
||||
*/
|
||||
const deleteCategoryClick = (category: IBlogCategory) => {
|
||||
|
||||
}
|
||||
</script>
|
||||
158
src/views/admin/blog/detail[id].vue
Normal file
158
src/views/admin/blog/detail[id].vue
Normal file
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div class="admin-module admin-blog-detail">
|
||||
<el-form ref="formRef" :model="blogStore.newBlog"
|
||||
:inline="true" :rules="rules"
|
||||
class="blog-form">
|
||||
<el-form-item label="标题" name="title" prop="title">
|
||||
<el-input v-model="blogStore.newBlog.title"
|
||||
:maxlength="20" show-word-limit clearable
|
||||
style="width: 300px"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="分类" name="category" prop="category">
|
||||
<el-select
|
||||
v-model="blogStore.newBlog.category"
|
||||
filterable allow-create placeholder="请选择分类" clearable
|
||||
@focus="focusCategoryEvent" style="width: 150px">
|
||||
<el-option
|
||||
v-for="(value, index) in blogStore.blogCategoryList"
|
||||
:key="index" :label="value.name" :value="value.name"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="置顶值">
|
||||
<el-input-number v-model="blogStore.newBlog.topValue"
|
||||
:min="1" :max="10" style="width: 120px"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="精品">
|
||||
<el-switch v-model="blogStore.newBlog.isGreat"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<MdEditor v-model="blogStore.newBlog.content" @onUploadImg="onUploadImg"/>
|
||||
|
||||
<div class="button-container">
|
||||
<el-button type="primary" @click="submitFormEvent">保存</el-button>
|
||||
</div>
|
||||
|
||||
<div class="back-button">
|
||||
<el-button type="primary" @click="backClick">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, onMounted, nextTick } from 'vue'
|
||||
import { useBlogStore } from '@/store/blog.ts'
|
||||
import { MdEditor } from 'md-editor-v3'
|
||||
import 'md-editor-v3/lib/style.css'
|
||||
import { ElLoading, ElMessage, FormInstance, FormRules } from 'element-plus'
|
||||
import { blogRules } from '@/utils/element/elRules.ts'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { validateBlogImage } from '@/utils/blog/blogUtil'
|
||||
import { doUploadFile } from 'vue3-common/utils/fileUtil'
|
||||
import { fileServiceUrl, serviceFileRootPath } from '@/utils'
|
||||
|
||||
const rules = reactive<FormRules>(blogRules)
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const blogStore = useBlogStore()
|
||||
|
||||
const focusCategoryEvent = async () => {
|
||||
await blogStore.queryAdminBlogCategory()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick(() => {
|
||||
formRef.value?.clearValidate()
|
||||
})
|
||||
|
||||
const blogId = route.params.id as number
|
||||
if (blogId > 0) {
|
||||
blogStore.blogApiType = 'UPDATE'
|
||||
await blogStore.queryAdminBlogById(route.params.id as number)
|
||||
blogStore.newBlog = blogStore.currentBlog
|
||||
} else {
|
||||
blogStore.blogApiType = 'ADD'
|
||||
blogStore.newBlog = blogStore.getEmptyBlog()
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 校验博客
|
||||
*/
|
||||
const validateBlog = (): boolean => {
|
||||
if (blogStore.newBlog.content === '') {
|
||||
ElMessage.error('请输入博客内容')
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交表单事件
|
||||
*/
|
||||
const submitFormEvent = () => {
|
||||
// 表单校验
|
||||
formRef.value?.validate().then(async () => {
|
||||
if (validateBlog()) {
|
||||
await blogStore.handleBlogApi()
|
||||
await router.push('/admin/blog/article')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const onUploadImg = async (files: File[], callback) => {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '正在上传图片 请等待',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
|
||||
if (validateBlogImage(files)) {
|
||||
const result = await doUploadFile(fileServiceUrl, files[0], blogStore.blogImagePath, false)
|
||||
// 显示在markdown中
|
||||
// 注意这里需要是数组的形式
|
||||
const urlArray = []
|
||||
urlArray.push({
|
||||
url: `${serviceFileRootPath}${result.url.replace(/\\/g, '/')}`,
|
||||
alt: '暂无图片',
|
||||
title: files[0].name
|
||||
})
|
||||
callback(urlArray)
|
||||
}
|
||||
|
||||
loading.close()
|
||||
}
|
||||
|
||||
const backClick = () => {
|
||||
router.push('/admin/blog/article')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.admin-blog-detail {
|
||||
position: relative;
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.blog-form {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.md-editor {
|
||||
height: 80vh;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
69
src/views/admin/blog/visit.vue
Normal file
69
src/views/admin/blog/visit.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
<el-table
|
||||
:data="blogInfo.blogVisitList"
|
||||
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="ip" label="IP" align="center" min-width="10%"/>
|
||||
<el-table-column prop="os" label="平台" align="center" min-width="10%" />
|
||||
<el-table-column prop="browser" label="浏览器" align="center" min-width="10%" />
|
||||
<el-table-column prop="uri" label="路径" align="center" min-width="10%" />
|
||||
<el-table-column prop="title" label="博客标题" align="center" min-width="10%" />
|
||||
<el-table-column prop="visitTime" label="访问时间" align="center" min-width="10%" />
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-model:current-page="blogInfo.pageInfo.currentPage"
|
||||
:page-size="blogInfo.pageInfo.pageSize"
|
||||
:total="blogInfo.pageInfo.totalSize"
|
||||
layout="total, prev, pager, next"
|
||||
@change="changePageClick"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive } from 'vue'
|
||||
import { IBlogVisit } from '@/types/blog.ts'
|
||||
import { queryBlogVisitApi } from '@/apis/blog.ts'
|
||||
import { tableCellStyle, tableHeaderStyle, tableRowStyle } from 'vue3-common/utils/elUtil'
|
||||
|
||||
const blogInfo = reactive({
|
||||
blogVisitList: [] as IBlogVisit[],
|
||||
pageInfo: {
|
||||
currentPage: 1,
|
||||
pageSize: 15,
|
||||
totalSize: 1
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await queryBlogVisit()
|
||||
})
|
||||
|
||||
/**
|
||||
* 切换页码
|
||||
* @param page 当前页码
|
||||
* @param pageSize 页码大小
|
||||
*/
|
||||
const changePageClick = async (page: number, pageSize: number) => {
|
||||
blogInfo.pageInfo.currentPage = page
|
||||
blogInfo.pageInfo.pageSize = pageSize
|
||||
await queryBlogVisit()
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看博客访问记录
|
||||
*/
|
||||
const queryBlogVisit = async () => {
|
||||
const { currentPage, pageSize } = blogInfo.pageInfo
|
||||
const result = await queryBlogVisitApi(currentPage, pageSize)
|
||||
blogInfo.blogVisitList = result.records
|
||||
blogInfo.pageInfo.totalSize = result.total
|
||||
}
|
||||
</script>
|
||||
13
src/views/admin/dashboard/index.vue
Normal file
13
src/views/admin/dashboard/index.vue
Normal file
@@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
首页
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
82
src/views/admin/meta.ts
Normal file
82
src/views/admin/meta.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { IRouteMetaConfig } from 'vue3-common/types'
|
||||
|
||||
export const adminMeta: IRouteMetaConfig = {
|
||||
'/admin/dashboard': {
|
||||
title: '首页',
|
||||
icon: 'admin-dashboard',
|
||||
order: 1,
|
||||
redirect: '/admin/dashboard/index'
|
||||
},
|
||||
'/admin/dashboard/index': {
|
||||
title: '首页',
|
||||
icon: ''
|
||||
},
|
||||
'/admin/blog': {
|
||||
title: '博客管理',
|
||||
icon: 'admin-blog',
|
||||
order: 2,
|
||||
redirect: '/admin/blog/article'
|
||||
},
|
||||
'/admin/blog/article': {
|
||||
title: '文章管理',
|
||||
icon: '',
|
||||
order: 1
|
||||
},
|
||||
'/admin/blog/category': {
|
||||
title: '类别管理',
|
||||
icon: '',
|
||||
order: 2
|
||||
},
|
||||
'/admin/blog/visit': {
|
||||
title: '访问记录',
|
||||
icon: '',
|
||||
order: 3
|
||||
},
|
||||
'/admin/blog/detail/:id': {
|
||||
title: '详细',
|
||||
icon: '',
|
||||
order: 4,
|
||||
hidden: true
|
||||
},
|
||||
'/admin/bill': {
|
||||
title: '账单管理',
|
||||
icon: 'admin-bill',
|
||||
order: 3,
|
||||
redirect: '/admin/bill/book'
|
||||
},
|
||||
'/admin/bill/book': {
|
||||
title: '账本管理',
|
||||
icon: '',
|
||||
order: 1
|
||||
},
|
||||
'/admin/bill/pay': {
|
||||
title: '账户管理',
|
||||
icon: '',
|
||||
order: 2
|
||||
},
|
||||
'/admin/bill/category': {
|
||||
title: '类别管理',
|
||||
icon: '',
|
||||
order: 3
|
||||
},
|
||||
'/admin/quartz': {
|
||||
title: '定时任务',
|
||||
icon: 'admin-quartz',
|
||||
order: 4,
|
||||
redirect: '/admin/quartz/index'
|
||||
},
|
||||
'/admin/quartz/index': {
|
||||
title: '定时任务',
|
||||
icon: ''
|
||||
},
|
||||
'/admin/account': {
|
||||
title: '账号管理',
|
||||
icon: 'admin-account',
|
||||
order: 5,
|
||||
redirect: '/admin/account/index'
|
||||
},
|
||||
'/admin/account/index': {
|
||||
title: '账号管理',
|
||||
icon: ''
|
||||
}
|
||||
}
|
||||
52
src/views/admin/quartz/index.vue
Normal file
52
src/views/admin/quartz/index.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="admin-module">
|
||||
<el-table
|
||||
:data="quartzInfo.quartzList"
|
||||
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="group" label="任务组别" align="center" min-width="20%"/>
|
||||
<el-table-column label="任务类型" align="center" min-width="20%">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.type === 'EMAIL'" type="success">邮件提醒</el-tag>
|
||||
<el-tag v-else type="danger">未知</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="content" label="任务内容" align="center"/>
|
||||
<el-table-column label="执行时间" align="center" width="200">
|
||||
<template #default="scope">
|
||||
{{ scope.row.executeTime }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任务状态" align="center" min-width="20%">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.status === 'NONE'" type="danger">不存在</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === 'NORMAL'" type="primary">正常执行</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === 'PAUSED'" type="warning">暂停</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === 'COMPLETE'" type="success">完成</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === 'ERROR'" type="danger">执行出错</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === 'BLOCKED'" type="danger">阻塞</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive } from 'vue'
|
||||
import { tableCellStyle, tableHeaderStyle, tableRowStyle } from 'vue3-common/utils/elUtil'
|
||||
import { IQuartzInfo } from '@/types/quartz'
|
||||
import { queryQuartzApi } from '@/apis/quartz'
|
||||
|
||||
const quartzInfo = reactive({
|
||||
quartzList: [] as IQuartzInfo[]
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
quartzInfo.quartzList = await queryQuartzApi()
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user