forked from gin/simple-template
feat: initial commit
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { usePostHook } from "./utils/hook";
|
||||
import { PureTableBar } from "@/components/RePureTableBar";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
|
||||
import Delete from "@iconify-icons/ep/delete";
|
||||
import Search from "@iconify-icons/ep/search";
|
||||
import Refresh from "@iconify-icons/ep/refresh";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
// TODO 这个导入声明好长 看看如何优化
|
||||
import { CommonUtils } from "@/utils/common";
|
||||
import PostFormModal from "@/views/system/post/post-form-modal.vue";
|
||||
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||
import { PostPageResponse } from "@/api/system/post";
|
||||
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||
|
||||
/** 组件name最好和菜单表中的router_name一致 */
|
||||
defineOptions({
|
||||
name: "Post"
|
||||
});
|
||||
|
||||
const loginLogStatusList = useUserStoreHook().dictionaryList["common.status"];
|
||||
|
||||
const tableRef = ref();
|
||||
|
||||
const searchFormRef = ref();
|
||||
const {
|
||||
searchFormParams,
|
||||
pageLoading,
|
||||
columns,
|
||||
dataList,
|
||||
pagination,
|
||||
timeRange,
|
||||
defaultSort,
|
||||
multipleSelection,
|
||||
onSearch,
|
||||
resetForm,
|
||||
onSortChanged,
|
||||
exportAllExcel,
|
||||
getPostList,
|
||||
handleDelete,
|
||||
handleBulkDelete
|
||||
} = usePostHook();
|
||||
|
||||
const opType = ref<"add" | "update">("add");
|
||||
const modalVisible = ref(false);
|
||||
const opRow = ref<PostPageResponse>();
|
||||
function openDialog(type: "add" | "update", row?: PostPageResponse) {
|
||||
opType.value = type;
|
||||
opRow.value = row;
|
||||
modalVisible.value = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main">
|
||||
<!-- 搜索栏 -->
|
||||
<el-form
|
||||
ref="searchFormRef"
|
||||
:inline="true"
|
||||
:model="searchFormParams"
|
||||
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]"
|
||||
>
|
||||
<el-form-item label="岗位编码" prop="postCode">
|
||||
<el-input
|
||||
v-model="searchFormParams.postCode"
|
||||
placeholder="请输入岗位编码"
|
||||
clearable
|
||||
class="!w-[200px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位名称" prop="postName">
|
||||
<el-input
|
||||
v-model="searchFormParams.postName"
|
||||
placeholder="请选择岗位名称"
|
||||
clearable
|
||||
class="!w-[200px]"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态:" prop="status">
|
||||
<el-select
|
||||
v-model="searchFormParams.status"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
class="!w-[180px]"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in loginLogStatusList"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker
|
||||
class="!w-[240px]"
|
||||
v-model="timeRange"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="useRenderIcon(Search)"
|
||||
:loading="pageLoading"
|
||||
@click="onSearch(tableRef)"
|
||||
>
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button
|
||||
:icon="useRenderIcon(Refresh)"
|
||||
@click="resetForm(searchFormRef, tableRef)"
|
||||
>
|
||||
重置
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- table bar 包裹 table -->
|
||||
<PureTableBar title="岗位列表" :columns="columns" @refresh="onSearch">
|
||||
<!-- 表格操作栏 -->
|
||||
<template #buttons>
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="useRenderIcon(AddFill)"
|
||||
@click="openDialog('add')"
|
||||
>
|
||||
新增岗位
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="useRenderIcon(Delete)"
|
||||
@click="handleBulkDelete(tableRef)"
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="CommonUtils.exportExcel(columns, dataList, '岗位列表')"
|
||||
>单页导出</el-button
|
||||
>
|
||||
<el-button type="primary" @click="exportAllExcel">全部导出</el-button>
|
||||
</template>
|
||||
<template v-slot="{ size, dynamicColumns }">
|
||||
<pure-table
|
||||
border
|
||||
ref="tableRef"
|
||||
align-whole="center"
|
||||
showOverflowTooltip
|
||||
table-layout="auto"
|
||||
:loading="pageLoading"
|
||||
:size="size"
|
||||
adaptive
|
||||
:data="dataList"
|
||||
:columns="dynamicColumns"
|
||||
:default-sort="defaultSort"
|
||||
:pagination="pagination"
|
||||
:paginationSmall="size === 'small' ? true : false"
|
||||
:header-cell-style="{
|
||||
background: 'var(--el-table-row-hover-bg-color)',
|
||||
color: 'var(--el-text-color-primary)'
|
||||
}"
|
||||
@page-size-change="getPostList"
|
||||
@page-current-change="getPostList"
|
||||
@sort-change="onSortChanged"
|
||||
@selection-change="
|
||||
rows => (multipleSelection = rows.map(item => item.postId))
|
||||
"
|
||||
>
|
||||
<template #operation="{ row }">
|
||||
<el-button
|
||||
class="reset-margin"
|
||||
link
|
||||
type="primary"
|
||||
:size="size"
|
||||
:icon="useRenderIcon(EditPen)"
|
||||
@click="openDialog('update', row)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-popconfirm
|
||||
:title="`是否确认删除编号为${row.postId}的这个岗位`"
|
||||
@confirm="handleDelete(row)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button
|
||||
class="reset-margin"
|
||||
link
|
||||
type="danger"
|
||||
:size="size"
|
||||
:icon="useRenderIcon(Delete)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</pure-table>
|
||||
</template>
|
||||
</PureTableBar>
|
||||
|
||||
<post-form-modal
|
||||
v-model="modalVisible"
|
||||
:type="opType"
|
||||
:row="opRow"
|
||||
@success="onSearch"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-dropdown-menu__item i) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.search-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,131 @@
|
||||
<script setup lang="ts">
|
||||
import VDialog from "@/components/VDialog/VDialog.vue";
|
||||
import { computed, reactive, ref } from "vue";
|
||||
import {
|
||||
AddPostCommand,
|
||||
PostPageResponse,
|
||||
UpdatePostCommand,
|
||||
addPostApi,
|
||||
updatePostApi
|
||||
} from "@/api/system/post";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
import { ElMessage, FormInstance, FormRules } from "element-plus";
|
||||
|
||||
interface Props {
|
||||
type: "add" | "update";
|
||||
modelValue: boolean;
|
||||
row?: PostPageResponse;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const emits = defineEmits<{
|
||||
(e: "update:modelValue", v: boolean): void;
|
||||
(e: "success"): void;
|
||||
}>();
|
||||
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set(v) {
|
||||
emits("update:modelValue", v);
|
||||
}
|
||||
});
|
||||
|
||||
const formData = reactive<AddPostCommand | UpdatePostCommand>({
|
||||
postId: 0,
|
||||
postCode: "",
|
||||
postName: "",
|
||||
postSort: 1,
|
||||
remark: "",
|
||||
status: ""
|
||||
});
|
||||
|
||||
const statusList = useUserStoreHook().dictionaryMap["common.status"];
|
||||
|
||||
const rules: FormRules = {
|
||||
postName: [
|
||||
{
|
||||
required: true,
|
||||
message: "岗位名称不能为空"
|
||||
}
|
||||
],
|
||||
postCode: [
|
||||
{
|
||||
required: true,
|
||||
message: "岗位编码不能为空"
|
||||
}
|
||||
],
|
||||
postSort: [
|
||||
{
|
||||
required: true,
|
||||
message: "岗位序号不能为空"
|
||||
}
|
||||
]
|
||||
};
|
||||
const formRef = ref<FormInstance>();
|
||||
function handleOpened() {
|
||||
if (props.row) {
|
||||
Object.assign(formData, props.row);
|
||||
} else {
|
||||
formRef.value?.resetFields();
|
||||
}
|
||||
}
|
||||
|
||||
const loading = ref(false);
|
||||
async function handleConfirm() {
|
||||
try {
|
||||
loading.value = true;
|
||||
if (props.type === "add") {
|
||||
await addPostApi(formData);
|
||||
} else if (props.type === "update") {
|
||||
await updatePostApi(formData as UpdatePostCommand);
|
||||
}
|
||||
ElMessage.info("提交成功");
|
||||
visible.value = false;
|
||||
emits("success");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ElMessage.error((e as Error)?.message || "提交失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog
|
||||
show-full-screen
|
||||
:fixed-body-height="false"
|
||||
use-body-scrolling
|
||||
:title="type === 'add' ? '新增岗位' : '更新岗位'"
|
||||
v-model="visible"
|
||||
:loading="loading"
|
||||
@confirm="handleConfirm"
|
||||
@cancel="visible = false"
|
||||
@opened="handleOpened"
|
||||
>
|
||||
<el-form :model="formData" label-width="120px" :rules="rules" ref="formRef">
|
||||
<el-form-item prop="postName" label="岗位名称" required inline-message>
|
||||
<el-input v-model="formData.postName" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="postCode" label="岗位编码" required>
|
||||
<el-input v-model="formData.postCode" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="postSort" label="岗位顺序" required>
|
||||
<el-input-number :min="1" v-model="formData.postSort" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" label="岗位状态">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="item in Object.keys(statusList)"
|
||||
:key="item"
|
||||
:label="statusList[item].value"
|
||||
>{{ statusList[item].label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" label="备注" style="margin-bottom: 0">
|
||||
<el-input type="textarea" v-model="formData.remark" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</v-dialog>
|
||||
</template>
|
||||
@@ -0,0 +1,229 @@
|
||||
import dayjs from "dayjs";
|
||||
import { message } from "@/utils/message";
|
||||
import { ElMessageBox, Sort } from "element-plus";
|
||||
import { reactive, ref, onMounted, toRaw, computed } from "vue";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
import { CommonUtils } from "@/utils/common";
|
||||
import { PaginationProps } from "@pureadmin/table";
|
||||
import {
|
||||
PostListCommand,
|
||||
getPostListApi,
|
||||
exportPostExcelApi,
|
||||
deletePostApi
|
||||
} from "@/api/system/post";
|
||||
|
||||
const statusMap = useUserStoreHook().dictionaryMap["common.status"];
|
||||
|
||||
export function usePostHook() {
|
||||
const defaultSort: Sort = {
|
||||
prop: "postSort",
|
||||
order: "ascending"
|
||||
};
|
||||
|
||||
const pagination: PaginationProps = {
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
currentPage: 1,
|
||||
background: true
|
||||
};
|
||||
|
||||
const timeRange = computed<[string, string] | null>({
|
||||
get() {
|
||||
if (searchFormParams.beginTime && searchFormParams.endTime) {
|
||||
return [searchFormParams.beginTime, searchFormParams.endTime];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
set(v) {
|
||||
if (v?.length === 2) {
|
||||
searchFormParams.beginTime = v[0];
|
||||
searchFormParams.endTime = v[1];
|
||||
} else {
|
||||
searchFormParams.beginTime = undefined;
|
||||
searchFormParams.endTime = undefined;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const searchFormParams = reactive<PostListCommand>({
|
||||
postCode: "",
|
||||
postName: "",
|
||||
status: undefined
|
||||
});
|
||||
|
||||
const dataList = ref([]);
|
||||
const pageLoading = ref(true);
|
||||
const multipleSelection = ref([]);
|
||||
const sortState = ref<Sort>(defaultSort);
|
||||
|
||||
const columns: TableColumnList = [
|
||||
{
|
||||
type: "selection",
|
||||
align: "left"
|
||||
},
|
||||
{
|
||||
label: "岗位编号",
|
||||
prop: "postId",
|
||||
minWidth: 100
|
||||
},
|
||||
{
|
||||
label: "岗位编码",
|
||||
prop: "postCode",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
label: "岗位名称",
|
||||
prop: "postName",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
label: "岗位排序",
|
||||
prop: "postSort",
|
||||
sortable: "custom",
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
label: "状态",
|
||||
prop: "status",
|
||||
minWidth: 120,
|
||||
cellRenderer: ({ row, props }) => (
|
||||
<el-tag
|
||||
size={props.size}
|
||||
type={statusMap[row.status].cssTag}
|
||||
effect="plain"
|
||||
>
|
||||
{statusMap[row.status].label}
|
||||
</el-tag>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: "创建时间",
|
||||
minWidth: 160,
|
||||
prop: "createTime",
|
||||
sortable: "custom",
|
||||
formatter: ({ createTime }) =>
|
||||
dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
|
||||
},
|
||||
{
|
||||
label: "操作",
|
||||
fixed: "right",
|
||||
width: 140,
|
||||
slot: "operation"
|
||||
}
|
||||
];
|
||||
|
||||
function onSortChanged(sort: Sort) {
|
||||
sortState.value = sort;
|
||||
// 表格列的排序变化的时候,需要重置分页
|
||||
pagination.currentPage = 1;
|
||||
getPostList();
|
||||
}
|
||||
|
||||
async function onSearch(tableRef) {
|
||||
// 点击搜索的时候,需要重置排序,重新排序的时候会重置分页并发起查询请求
|
||||
tableRef.getTableRef().sort("postSort", "ascending");
|
||||
}
|
||||
|
||||
function resetForm(formEl, tableRef) {
|
||||
if (!formEl) return;
|
||||
// 清空查询参数
|
||||
formEl.resetFields();
|
||||
// 清空时间查询 TODO 这块有点繁琐 有可以优化的地方吗?
|
||||
// Form组件的resetFields方法无法清除datepicker里面的数据。
|
||||
searchFormParams.beginTime = undefined;
|
||||
searchFormParams.endTime = undefined;
|
||||
// 重置分页并查询
|
||||
onSearch(tableRef);
|
||||
}
|
||||
|
||||
async function getPostList() {
|
||||
pageLoading.value = true;
|
||||
CommonUtils.fillSortParams(searchFormParams, sortState.value);
|
||||
CommonUtils.fillPaginationParams(searchFormParams, pagination);
|
||||
|
||||
const { data } = await getPostListApi(toRaw(searchFormParams)).finally(
|
||||
() => {
|
||||
pageLoading.value = false;
|
||||
}
|
||||
);
|
||||
dataList.value = data.rows;
|
||||
pagination.total = data.total;
|
||||
}
|
||||
|
||||
async function exportAllExcel() {
|
||||
if (sortState.value != null) {
|
||||
CommonUtils.fillSortParams(searchFormParams, sortState.value);
|
||||
}
|
||||
CommonUtils.fillPaginationParams(searchFormParams, pagination);
|
||||
CommonUtils.fillTimeRangeParams(searchFormParams, timeRange.value);
|
||||
|
||||
exportPostExcelApi(toRaw(searchFormParams), "岗位数据.xlsx");
|
||||
}
|
||||
|
||||
async function handleDelete(row) {
|
||||
await deletePostApi([row.postId]).then(() => {
|
||||
message(`您删除了编号为${row.postId}的这条岗位数据`, {
|
||||
type: "success"
|
||||
});
|
||||
// 刷新列表
|
||||
getPostList();
|
||||
});
|
||||
}
|
||||
|
||||
async function handleBulkDelete(tableRef) {
|
||||
if (multipleSelection.value.length === 0) {
|
||||
message("请选择需要删除的数据", { type: "warning" });
|
||||
return;
|
||||
}
|
||||
|
||||
ElMessageBox.confirm(
|
||||
`确认要<strong>删除</strong>编号为<strong style='color:var(--el-color-primary)'>[ ${multipleSelection.value} ]</strong>的岗位数据吗?`,
|
||||
"系统提示",
|
||||
{
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning",
|
||||
dangerouslyUseHTMLString: true,
|
||||
draggable: true
|
||||
}
|
||||
)
|
||||
.then(async () => {
|
||||
await deletePostApi(multipleSelection.value).then(() => {
|
||||
message(`您删除了编号为[ ${multipleSelection.value} ]的岗位数据`, {
|
||||
type: "success"
|
||||
});
|
||||
// 刷新列表
|
||||
getPostList();
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
message("取消删除", {
|
||||
type: "info"
|
||||
});
|
||||
// 清空checkbox选择的数据
|
||||
tableRef.getTableRef().clearSelection();
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(getPostList);
|
||||
|
||||
return {
|
||||
searchFormParams,
|
||||
pageLoading,
|
||||
columns,
|
||||
dataList,
|
||||
pagination,
|
||||
defaultSort,
|
||||
timeRange,
|
||||
multipleSelection,
|
||||
onSearch,
|
||||
onSortChanged,
|
||||
exportAllExcel,
|
||||
// exportExcel,
|
||||
getPostList,
|
||||
resetForm,
|
||||
handleDelete,
|
||||
handleBulkDelete
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user