feat(projects): 1:恢复岗位页面;2:国际化功能摒弃;
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { defineConfig } from '@soybeanjs/eslint-config';
|
||||
import tsEslintPlugin from '@typescript-eslint/eslint-plugin';
|
||||
|
||||
export default defineConfig(
|
||||
{ vue: true, unocss: true },
|
||||
@@ -20,5 +21,22 @@ export default defineConfig(
|
||||
],
|
||||
'unocss/order-attributify': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts', '**/*.tsx', '**/*.vue'],
|
||||
plugins: {
|
||||
'@typescript-eslint': tsEslintPlugin
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
varsIgnorePattern: '^_',
|
||||
argsIgnorePattern: '^_',
|
||||
caughtErrorsIgnorePattern: '^_',
|
||||
ignoreRestSiblings: true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -67,3 +67,11 @@ export const menuRouteKindRecord: Record<Api.SystemManage.MenuRouteKind, App.I18
|
||||
};
|
||||
|
||||
export const menuRouteKindOptions = transformRecordToOption(menuRouteKindRecord);
|
||||
|
||||
export const postTypeRecord: Record<Api.SystemManage.PostType, string> = {
|
||||
management: '管理岗',
|
||||
technical: '技术岗',
|
||||
business: '业务岗'
|
||||
};
|
||||
|
||||
export const postTypeOptions = transformRecordToOption(postTypeRecord);
|
||||
|
||||
@@ -40,12 +40,6 @@ const { isFullscreen, toggle } = useFullscreen();
|
||||
<div>
|
||||
<FullScreen v-if="!appStore.isMobile" :full="isFullscreen" @click="toggle" />
|
||||
</div>
|
||||
<LangSwitch
|
||||
v-if="themeStore.header.multilingual.visible"
|
||||
:lang="appStore.locale"
|
||||
:lang-options="appStore.localeOptions"
|
||||
@change-lang="appStore.changeLocale"
|
||||
/>
|
||||
<ThemeSchemaSwitch
|
||||
:theme-schema="themeStore.themeScheme"
|
||||
:is-dark="themeStore.darkMode"
|
||||
|
||||
@@ -121,10 +121,7 @@ const isWrapperScrollMode = computed(() => themeStore.layout.scrollMode === 'wra
|
||||
placeholder="CN-RDMS"
|
||||
/>
|
||||
</SettingItem>
|
||||
<SettingItem key="9" :label="$t('theme.header.multilingual.visible')">
|
||||
<ElSwitch v-model="themeStore.header.multilingual.visible" />
|
||||
</SettingItem>
|
||||
<SettingItem key="10" :label="$t('theme.header.globalSearch.visible')">
|
||||
<SettingItem key="9" :label="$t('theme.header.globalSearch.visible')">
|
||||
<ElSwitch v-model="themeStore.header.globalSearch.visible" />
|
||||
</SettingItem>
|
||||
</TransitionGroup>
|
||||
|
||||
@@ -243,6 +243,59 @@ export function fetchGetPostSimpleList() {
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取岗位分页 */
|
||||
export function fetchGetPostPage(params?: Api.SystemManage.PostSearchParams) {
|
||||
return request<Api.SystemManage.PostList>({
|
||||
url: `${POST_PREFIX}/page`,
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取岗位详情 */
|
||||
export function fetchGetPost(id: number) {
|
||||
return request<Api.SystemManage.Post>({
|
||||
url: `${POST_PREFIX}/get`,
|
||||
method: 'get',
|
||||
params: { id }
|
||||
});
|
||||
}
|
||||
|
||||
/** 创建岗位 */
|
||||
export function fetchCreatePost(data: Api.SystemManage.SavePostParams) {
|
||||
return request<number>({
|
||||
url: `${POST_PREFIX}/create`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/** 更新岗位 */
|
||||
export function fetchUpdatePost(data: { id: number } & Api.SystemManage.SavePostParams) {
|
||||
return request<boolean>({
|
||||
url: `${POST_PREFIX}/update`,
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除岗位 */
|
||||
export function fetchDeletePost(id: number) {
|
||||
return request<boolean>({
|
||||
url: `${POST_PREFIX}/delete`,
|
||||
method: 'delete',
|
||||
params: { id }
|
||||
});
|
||||
}
|
||||
|
||||
/** 批量删除岗位 */
|
||||
export function fetchBatchDeletePost(ids: number[]) {
|
||||
return request<boolean>({
|
||||
url: `${POST_PREFIX}/delete-list?${createBatchDeleteQuery(ids)}`,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取用户分页 */
|
||||
export function fetchGetUserPage(params?: Api.SystemManage.UserSearchParams) {
|
||||
return request<Api.SystemManage.UserList>({
|
||||
|
||||
@@ -28,7 +28,7 @@ export const themeSettings: App.Theme.ThemeSetting = {
|
||||
showIcon: true
|
||||
},
|
||||
multilingual: {
|
||||
visible: true
|
||||
visible: false
|
||||
},
|
||||
globalSearch: {
|
||||
visible: true
|
||||
|
||||
20
src/typings/api/system-manage.d.ts
vendored
20
src/typings/api/system-manage.d.ts
vendored
@@ -177,6 +177,18 @@ declare namespace Api {
|
||||
|
||||
type PostType = 'management' | 'technical' | 'business';
|
||||
|
||||
interface Post {
|
||||
id: number;
|
||||
name: string;
|
||||
code?: string | null;
|
||||
postType?: PostType | null;
|
||||
levelRank?: number | null;
|
||||
sort?: number | null;
|
||||
status: CommonStatus;
|
||||
remark?: string | null;
|
||||
createTime: number;
|
||||
}
|
||||
|
||||
interface PostSimple {
|
||||
id: number;
|
||||
name: string;
|
||||
@@ -188,6 +200,14 @@ declare namespace Api {
|
||||
|
||||
type PostSimpleList = PostSimple[];
|
||||
|
||||
type PostSearchParams = CommonType.RecordNullable<Pick<Post, 'name' | 'code' | 'postType' | 'status'>> & PageParams;
|
||||
|
||||
type SavePostParams = Pick<Post, 'name' | 'code' | 'postType' | 'levelRank' | 'sort' | 'status'> & {
|
||||
remark?: string | null;
|
||||
};
|
||||
|
||||
type PostList = PageResult<Post>;
|
||||
|
||||
type RoleSimple = Pick<Role, 'id' | 'name' | 'code' | 'status' | 'sort'>;
|
||||
|
||||
type RoleSimpleList = RoleSimple[];
|
||||
|
||||
@@ -3,7 +3,6 @@ import { computed } from 'vue';
|
||||
import type { Component } from 'vue';
|
||||
import { getPaletteColorByNumber, mixColor } from '@sa/color';
|
||||
import { loginModuleRecord } from '@/constants/app';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { $t } from '@/locales';
|
||||
import PwdLogin from './modules/pwd-login.vue';
|
||||
@@ -18,7 +17,6 @@ interface Props {
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
|
||||
interface LoginModule {
|
||||
@@ -61,13 +59,6 @@ const bgColor = computed(() => {
|
||||
class="text-20px lt-sm:text-18px"
|
||||
@switch="themeStore.toggleThemeScheme"
|
||||
/>
|
||||
<LangSwitch
|
||||
v-if="themeStore.header.multilingual.visible"
|
||||
:lang="appStore.locale"
|
||||
:lang-options="appStore.localeOptions"
|
||||
:show-tooltip="false"
|
||||
@change-lang="appStore.changeLocale"
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<main class="pt-15px">
|
||||
|
||||
@@ -1,3 +1,319 @@
|
||||
<script setup lang="tsx">
|
||||
import { nextTick, reactive, ref } from 'vue';
|
||||
import type { TableInstance } from 'element-plus';
|
||||
import { ElButton, ElPopconfirm, ElTag } from 'element-plus';
|
||||
import dayjs from 'dayjs';
|
||||
import { useBoolean } from '@sa/hooks';
|
||||
import { fetchBatchDeletePost, fetchDeletePost, fetchGetPostPage } from '@/service/api';
|
||||
import { useUIPaginatedTable } from '@/hooks/common/table';
|
||||
import BusinessTableActionCell from '@/components/custom/business-table-action-cell';
|
||||
import PostOperateDialog from './modules/post-operate-dialog.vue';
|
||||
import PostSearch from './modules/post-search.vue';
|
||||
|
||||
defineOptions({ name: 'PostManage' });
|
||||
|
||||
function getInitSearchParams(): Api.SystemManage.PostSearchParams {
|
||||
return {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
code: undefined,
|
||||
postType: undefined,
|
||||
status: undefined
|
||||
};
|
||||
}
|
||||
|
||||
function transformPageResult(response: Awaited<ReturnType<typeof fetchGetPostPage>>, pageNo: number, pageSize: number) {
|
||||
if (!response.error) {
|
||||
return {
|
||||
data: response.data.list,
|
||||
pageNum: pageNo,
|
||||
pageSize,
|
||||
total: response.data.total
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
data: [],
|
||||
pageNum: pageNo,
|
||||
pageSize,
|
||||
total: 0
|
||||
};
|
||||
}
|
||||
|
||||
function formatTime(value?: number | null) {
|
||||
if (!value) {
|
||||
return '--';
|
||||
}
|
||||
|
||||
return dayjs(value).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
|
||||
function getStatusTagType(status: Api.SystemManage.CommonStatus): UI.ThemeColor {
|
||||
return status === 0 ? 'success' : 'warning';
|
||||
}
|
||||
|
||||
function getStatusLabel(status: Api.SystemManage.CommonStatus) {
|
||||
return status === 0 ? '启用' : '停用';
|
||||
}
|
||||
|
||||
function getPostTypeLabel(type?: Api.SystemManage.PostType | null) {
|
||||
if (!type) {
|
||||
return '--';
|
||||
}
|
||||
|
||||
const postTypeLabelMap: Record<Api.SystemManage.PostType, string> = {
|
||||
management: '管理岗',
|
||||
technical: '技术岗',
|
||||
business: '业务岗'
|
||||
};
|
||||
|
||||
return postTypeLabelMap[type];
|
||||
}
|
||||
|
||||
const searchParams = reactive(getInitSearchParams());
|
||||
const postTableRef = ref<TableInstance>();
|
||||
const postCheckedRowKeys = ref<number[]>([]);
|
||||
|
||||
const { columns, columnChecks, data, loading, getData, getDataByPage, mobilePagination } = useUIPaginatedTable({
|
||||
paginationProps: {
|
||||
currentPage: searchParams.pageNo,
|
||||
pageSize: searchParams.pageSize
|
||||
},
|
||||
api: () => fetchGetPostPage(searchParams),
|
||||
transform: response => transformPageResult(response, searchParams.pageNo, searchParams.pageSize),
|
||||
onPaginationParamsChange: params => {
|
||||
searchParams.pageNo = params.currentPage ?? 1;
|
||||
searchParams.pageSize = params.pageSize ?? 10;
|
||||
},
|
||||
columns: () => [
|
||||
{ prop: 'selection', type: 'selection', width: 48 },
|
||||
{ prop: 'index', type: 'index', label: '序号', width: 64 },
|
||||
{ prop: 'name', label: '岗位名称', minWidth: 160, showOverflowTooltip: true },
|
||||
{ prop: 'code', label: '岗位编码', minWidth: 180, showOverflowTooltip: true },
|
||||
{
|
||||
prop: 'postType',
|
||||
label: '岗位类型',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
formatter: row => getPostTypeLabel(row.postType)
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '岗位状态',
|
||||
width: 110,
|
||||
align: 'center',
|
||||
formatter: row => <ElTag type={getStatusTagType(row.status)}>{getStatusLabel(row.status)}</ElTag>
|
||||
},
|
||||
{
|
||||
prop: 'levelRank',
|
||||
label: '岗位职级',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
formatter: row => String(row.levelRank ?? '--')
|
||||
},
|
||||
{ prop: 'sort', label: '排序', width: 90, align: 'center' },
|
||||
{
|
||||
prop: 'remark',
|
||||
label: '备注',
|
||||
minWidth: 180,
|
||||
showOverflowTooltip: true,
|
||||
formatter: row => row.remark || '--'
|
||||
},
|
||||
{
|
||||
prop: 'createTime',
|
||||
label: '创建时间',
|
||||
minWidth: 170,
|
||||
formatter: row => formatTime(row.createTime)
|
||||
},
|
||||
{
|
||||
prop: 'operate',
|
||||
label: '操作',
|
||||
width: 196,
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
formatter: row => (
|
||||
<BusinessTableActionCell
|
||||
actions={[
|
||||
{
|
||||
key: 'edit',
|
||||
label: '编辑',
|
||||
buttonType: 'primary',
|
||||
onClick: () => openEdit(row)
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
label: '删除',
|
||||
buttonType: 'danger',
|
||||
onClick: () => handleDeleteAction(row)
|
||||
}
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { bool: operateVisible, setTrue: openOperateModal, setFalse: closeOperateModal } = useBoolean();
|
||||
const operateType = ref<UI.TableOperateType>('add');
|
||||
const editingData = ref<Api.SystemManage.Post | null>(null);
|
||||
|
||||
function openAdd() {
|
||||
operateType.value = 'add';
|
||||
editingData.value = null;
|
||||
openOperateModal();
|
||||
}
|
||||
|
||||
function openEdit(item: Api.SystemManage.Post) {
|
||||
operateType.value = 'edit';
|
||||
editingData.value = item;
|
||||
openOperateModal();
|
||||
}
|
||||
|
||||
async function handleDelete(item: Api.SystemManage.Post) {
|
||||
const { error } = await fetchDeletePost(item.id);
|
||||
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.$message?.success('删除成功');
|
||||
|
||||
await reloadPostTable();
|
||||
}
|
||||
|
||||
async function handleDeleteAction(row: Api.SystemManage.Post) {
|
||||
try {
|
||||
await window.$messageBox?.confirm('确认删除当前岗位吗?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
});
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
await handleDelete(row);
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
if (!postCheckedRowKeys.value.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { error } = await fetchBatchDeletePost(postCheckedRowKeys.value);
|
||||
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.$message?.success('删除成功');
|
||||
await reloadPostTable();
|
||||
}
|
||||
|
||||
function handlePostSelectionChange(rows: Api.SystemManage.Post[]) {
|
||||
postCheckedRowKeys.value = rows.map(item => item.id);
|
||||
}
|
||||
|
||||
async function reloadPostTable(page = searchParams.pageNo) {
|
||||
postCheckedRowKeys.value = [];
|
||||
await getDataByPage(page);
|
||||
await nextTick();
|
||||
postTableRef.value?.clearSelection();
|
||||
}
|
||||
|
||||
function resetSearchParams() {
|
||||
Object.assign(searchParams, getInitSearchParams());
|
||||
reloadPostTable(1);
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
reloadPostTable(1);
|
||||
}
|
||||
|
||||
function handleSubmitted(postId: number) {
|
||||
closeOperateModal();
|
||||
reloadPostTable();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>岗位管理</h1>
|
||||
<div class="flex-col-stretch gap-16px overflow-hidden">
|
||||
<PostSearch v-model:model="searchParams" @reset="resetSearchParams" @search="handleSearch" />
|
||||
|
||||
<ElCard class="flex-1-hidden card-wrapper" body-class="post-table-card-body">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between gap-12px">
|
||||
<div class="flex items-center gap-10px">
|
||||
<p>岗位列表</p>
|
||||
<ElTag effect="plain">{{ mobilePagination.total || data.length }}</ElTag>
|
||||
</div>
|
||||
<TableHeaderOperation
|
||||
v-model:columns="columnChecks"
|
||||
:disabled-delete="true"
|
||||
:loading="loading"
|
||||
@refresh="reloadPostTable"
|
||||
>
|
||||
<template #default>
|
||||
<ElButton plain type="primary" @click="openAdd">
|
||||
<template #icon>
|
||||
<icon-ic-round-plus class="text-icon" />
|
||||
</template>
|
||||
新增
|
||||
</ElButton>
|
||||
<ElPopconfirm title="确认删除选中的岗位吗?" @confirm="handleBatchDelete">
|
||||
<template #reference>
|
||||
<ElButton type="danger" plain :disabled="postCheckedRowKeys.length === 0">
|
||||
<template #icon>
|
||||
<icon-ic-round-delete class="text-icon" />
|
||||
</template>
|
||||
批量删除
|
||||
</ElButton>
|
||||
</template>
|
||||
</ElPopconfirm>
|
||||
</template>
|
||||
</TableHeaderOperation>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="flex-1">
|
||||
<ElTable
|
||||
ref="postTableRef"
|
||||
v-loading="loading"
|
||||
height="100%"
|
||||
border
|
||||
row-key="id"
|
||||
:data="data"
|
||||
@selection-change="handlePostSelectionChange"
|
||||
>
|
||||
<ElTableColumn v-for="col in columns" :key="String(col.prop)" v-bind="col" />
|
||||
</ElTable>
|
||||
</div>
|
||||
|
||||
<div class="mt-20px flex justify-end">
|
||||
<ElPagination
|
||||
v-if="mobilePagination.total"
|
||||
layout="total,prev,pager,next,sizes"
|
||||
v-bind="mobilePagination"
|
||||
@current-change="mobilePagination['current-change']"
|
||||
@size-change="mobilePagination['size-change']"
|
||||
/>
|
||||
</div>
|
||||
</ElCard>
|
||||
|
||||
<PostOperateDialog
|
||||
v-model:visible="operateVisible"
|
||||
:operate-type="operateType"
|
||||
:row-data="editingData"
|
||||
@submitted="handleSubmitted"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.post-table-card-body) {
|
||||
height: calc(100% - 56px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
|
||||
202
src/views/system/post/modules/post-operate-dialog.vue
Normal file
202
src/views/system/post/modules/post-operate-dialog.vue
Normal file
@@ -0,0 +1,202 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, ref, watch } from 'vue';
|
||||
import { postTypeOptions } from '@/constants/business';
|
||||
import { fetchCreatePost, fetchGetPost, fetchUpdatePost } from '@/service/api';
|
||||
import { useForm, useFormRules } from '@/hooks/common/form';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
|
||||
defineOptions({ name: 'PostOperateDialog' });
|
||||
|
||||
interface Props {
|
||||
operateType: UI.TableOperateType;
|
||||
rowData?: Api.SystemManage.Post | null;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
submitted: [postId: number];
|
||||
}>();
|
||||
|
||||
const visible = defineModel<boolean>('visible', {
|
||||
default: false
|
||||
});
|
||||
|
||||
const { formRef, validate } = useForm();
|
||||
const { createRequiredRule } = useFormRules();
|
||||
|
||||
const detailLoading = ref(false);
|
||||
const submitting = ref(false);
|
||||
const isEdit = computed(() => props.operateType === 'edit');
|
||||
const statusOptions = [
|
||||
{ label: '启用', value: 0 as const },
|
||||
{ label: '停用', value: 1 as const }
|
||||
];
|
||||
|
||||
const title = computed(() => {
|
||||
const titleMap: Record<UI.TableOperateType, string> = {
|
||||
add: '新增岗位',
|
||||
edit: '编辑岗位'
|
||||
};
|
||||
|
||||
return titleMap[props.operateType];
|
||||
});
|
||||
|
||||
type Model = Api.SystemManage.SavePostParams;
|
||||
|
||||
const model = ref(createDefaultModel());
|
||||
|
||||
function createDefaultModel(): Model {
|
||||
return {
|
||||
name: '',
|
||||
code: '',
|
||||
postType: null,
|
||||
levelRank: null,
|
||||
sort: 0,
|
||||
status: 0,
|
||||
remark: ''
|
||||
};
|
||||
}
|
||||
|
||||
const rules = {
|
||||
name: createRequiredRule('请输入岗位名称'),
|
||||
code: createRequiredRule('请输入岗位编码'),
|
||||
postType: createRequiredRule('请选择岗位类型'),
|
||||
sort: createRequiredRule('请输入排序'),
|
||||
status: createRequiredRule('请选择岗位状态')
|
||||
} satisfies Record<string, App.Global.FormRule>;
|
||||
|
||||
function closeModal() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
async function initModel() {
|
||||
model.value = createDefaultModel();
|
||||
|
||||
if (!isEdit.value || !props.rowData) {
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
return;
|
||||
}
|
||||
|
||||
detailLoading.value = true;
|
||||
|
||||
const { error, data } = await fetchGetPost(props.rowData.id);
|
||||
|
||||
detailLoading.value = false;
|
||||
|
||||
if (!error) {
|
||||
model.value = {
|
||||
name: data.name,
|
||||
code: data.code ?? '',
|
||||
postType: data.postType ?? null,
|
||||
levelRank: data.levelRank ?? null,
|
||||
sort: data.sort ?? 0,
|
||||
status: data.status,
|
||||
remark: data.remark ?? ''
|
||||
};
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
formRef.value?.clearValidate();
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
await validate();
|
||||
|
||||
submitting.value = true;
|
||||
|
||||
const submitData: Api.SystemManage.SavePostParams = {
|
||||
...model.value,
|
||||
name: model.value.name.trim(),
|
||||
code: model.value.code?.trim() || null,
|
||||
remark: model.value.remark?.trim() || null
|
||||
};
|
||||
|
||||
const request =
|
||||
isEdit.value && props.rowData
|
||||
? await fetchUpdatePost({ id: props.rowData.id, ...submitData })
|
||||
: await fetchCreatePost(submitData);
|
||||
|
||||
const { error, data } = await request;
|
||||
|
||||
submitting.value = false;
|
||||
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
const postId = isEdit.value && props.rowData ? props.rowData.id : Number(data);
|
||||
|
||||
window.$message?.success(isEdit.value ? '修改成功' : '新增成功');
|
||||
|
||||
closeModal();
|
||||
emit('submitted', postId);
|
||||
}
|
||||
|
||||
watch(visible, value => {
|
||||
if (value) {
|
||||
initModel();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BusinessFormDialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
preset="md"
|
||||
:loading="detailLoading"
|
||||
:confirm-loading="submitting"
|
||||
:scrollbar="false"
|
||||
@confirm="handleSubmit"
|
||||
>
|
||||
<ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
|
||||
<ElRow :gutter="16">
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="岗位名称" prop="name">
|
||||
<ElInput v-model="model.name" placeholder="请输入岗位名称" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="岗位编码" prop="code">
|
||||
<ElInput v-model="model.code" placeholder="请输入岗位编码" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="岗位类型" prop="postType">
|
||||
<ElSelect v-model="model.postType" class="w-full" placeholder="请选择岗位类型">
|
||||
<ElOption v-for="{ label, value } in postTypeOptions" :key="value" :label="label" :value="value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="岗位职级" prop="levelRank">
|
||||
<ElInputNumber v-model="model.levelRank" class="w-full" :min="0" placeholder="请输入岗位职级" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="排序" prop="sort">
|
||||
<ElInputNumber v-model="model.sort" class="w-full" :min="0" placeholder="请输入排序" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="岗位状态" prop="status">
|
||||
<ElRadioGroup v-model="model.status" class="business-form-radio-group">
|
||||
<ElRadio v-for="{ label, value } in statusOptions" :key="value" :value="value">
|
||||
{{ label }}
|
||||
</ElRadio>
|
||||
</ElRadioGroup>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="备注" prop="remark">
|
||||
<ElInput v-model="model.remark" type="textarea" :rows="4" placeholder="请输入备注" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</ElForm>
|
||||
</BusinessFormDialog>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
64
src/views/system/post/modules/post-search.vue
Normal file
64
src/views/system/post/modules/post-search.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { postTypeOptions } from '@/constants/business';
|
||||
import TableSearchPanel from '@/components/custom/table-search-panel.vue';
|
||||
|
||||
defineOptions({ name: 'PostSearch' });
|
||||
|
||||
const emit = defineEmits<{
|
||||
reset: [];
|
||||
search: [];
|
||||
}>();
|
||||
|
||||
const model = defineModel<Api.SystemManage.PostSearchParams>('model', { required: true });
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '启用', value: 0 as const },
|
||||
{ label: '停用', value: 1 as const }
|
||||
];
|
||||
|
||||
const keyword = computed({
|
||||
get() {
|
||||
return model.value.name ?? model.value.code ?? '';
|
||||
},
|
||||
set(value: string) {
|
||||
const text = value.trim() || undefined;
|
||||
model.value.name = text;
|
||||
model.value.code = text;
|
||||
}
|
||||
});
|
||||
|
||||
function reset() {
|
||||
emit('reset');
|
||||
}
|
||||
|
||||
function search() {
|
||||
emit('search');
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableSearchPanel :model="model" :action-col-lg="8" @reset="reset" @search="search">
|
||||
<ElCol :lg="8" :md="12" :sm="12">
|
||||
<ElFormItem label="岗位名称" prop="name">
|
||||
<ElInput v-model="keyword" clearable placeholder="请输入岗位名称或岗位编码" />
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="8" :md="12" :sm="12">
|
||||
<ElFormItem label="岗位类型" prop="postType">
|
||||
<ElSelect v-model="model.postType" clearable placeholder="请选择岗位类型">
|
||||
<ElOption v-for="{ label, value } in postTypeOptions" :key="value" :label="label" :value="value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :lg="8" :md="12" :sm="12">
|
||||
<ElFormItem label="岗位状态" prop="status">
|
||||
<ElSelect v-model="model.status" clearable placeholder="请选择岗位状态">
|
||||
<ElOption v-for="{ label, value } in statusOptions" :key="value" :label="label" :value="value" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</TableSearchPanel>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
Reference in New Issue
Block a user