New file |
| | |
| | | export enum SearchType { |
| | | /**身份 */ |
| | | Identity = 210, |
| | | /**学历 */ |
| | | Education = 220, |
| | | /**岗位 */ |
| | | Position = 230, |
| | | /**证书类型 */ |
| | | CertificateType = 240, |
| | | /**福利 */ |
| | | Welfare = 250, |
| | | /**行业类型 */ |
| | | IndustryCategory = 260, |
| | | } |
| | | |
| | | export const SearchTypeText = { |
| | | [SearchType.Identity]: '身份', |
| | | [SearchType.Education]: '学历', |
| | | [SearchType.Position]: '岗位', |
| | | [SearchType.CertificateType]: '证书类型', |
| | | [SearchType.Welfare]: '福利', |
| | | [SearchType.IndustryCategory]: '行业类型', |
| | | }; |
| | |
| | | Role = 1, |
| | | User, |
| | | } |
| | | |
| | | export const BooleanOptions = [ |
| | | { label: '是', value: true }, |
| | | { label: '否', value: false }, |
| | | ]; |
| | |
| | | export * from './menu'; |
| | | export * from './role'; |
| | | export * from './app'; |
| | | export * from './dic'; |
New file |
| | |
| | | import * as searchSettingServices from '@/services/api/SearchSetting'; |
| | | import { useQuery } from '@tanstack/vue-query'; |
| | | import { useQueryClient } from '@tanstack/vue-query'; |
| | | import { SearchType } from '@/constants'; |
| | | |
| | | type UseSearchSettingTypeOptions = { |
| | | searchType: number; |
| | | belongType?: number; |
| | | onSuccess?: (data: API.GetTypeSearchSettingList[]) => any; |
| | | }; |
| | | |
| | | export function useSearchSettingType({ |
| | | searchType, |
| | | belongType = null, |
| | | onSuccess, |
| | | }: UseSearchSettingTypeOptions) { |
| | | const { data, refetch } = useQuery({ |
| | | queryKey: ['searchSettingServices/getTypeSearchSettingList', { searchType, belongType }], |
| | | queryFn: async () => { |
| | | return await searchSettingServices.getTypeSearchSettingList( |
| | | { |
| | | searchType: searchType, |
| | | belongType: belongType, |
| | | }, |
| | | { showLoading: false } |
| | | ); |
| | | }, |
| | | placeholderData: () => [] as API.GetTypeSearchSettingList[], |
| | | onSuccess(data) { |
| | | onSuccess?.(data); |
| | | }, |
| | | }); |
| | | |
| | | const queryClient = useQueryClient(); |
| | | |
| | | async function ensureSearchSettingType() { |
| | | return await queryClient.ensureQueryData({ |
| | | queryKey: [ |
| | | 'searchSettingServices/getTypeSearchSettingList', |
| | | { searchType: searchType, belongType: belongType }, |
| | | ], |
| | | }); |
| | | } |
| | | |
| | | function getSearchSettingTypeNameById(id: string) { |
| | | return data.value.find((x) => x.id === id)?.name ?? ''; |
| | | } |
| | | |
| | | return { |
| | | searchSettingTypeList: data, |
| | | ensureSearchSettingType, |
| | | refetchSearchSettingType: refetch, |
| | | getSearchSettingTypeNameById, |
| | | }; |
| | | } |
| | |
| | | export * from './useEvent'; |
| | | export * from './useUser'; |
| | | export * from './help'; |
| | | export * from './dic'; |
| | |
| | | clickCount?: number; |
| | | src?: string; |
| | | isRecommend?: boolean; |
| | | searchType?: number; |
| | | } |
| | | |
| | | interface GetSearchSettingListInput { |
| | |
| | | requestInterceptors: [ |
| | | [ |
| | | (config) => { |
| | | console.log('req config: ', config); |
| | | const $config = config; |
| | | // 开启进度条动画 |
| | | if (config.needNProcess) { |
New file |
| | |
| | | <template> |
| | | <LoadingLayout :loading="state.loading"> |
| | | <AppContainer> |
| | | <ProTableQueryFilterBar @on-reset="reset"> |
| | | <template #query> |
| | | <QueryFilterItem> |
| | | <FieldSelect |
| | | v-model="extraParamState.searchType" |
| | | @change="getList()" |
| | | :value-enum="SearchTypeText" |
| | | placeholder="请选择所属类别" |
| | | ></FieldSelect> |
| | | </QueryFilterItem> |
| | | <QueryFilterItem v-if="extraParamState.searchType === SearchType.Position"> |
| | | <FieldSelect |
| | | v-model="extraParamState.parentId" |
| | | @change="getList()" |
| | | :value-enum="typeList" |
| | | enum-label-key="name" |
| | | enum-value-key="id" |
| | | placeholder="请选择行业类型" |
| | | clearable |
| | | ></FieldSelect> |
| | | </QueryFilterItem> |
| | | <QueryFilterItem> |
| | | <SearchInput |
| | | v-model="extraParamState.name" |
| | | style="width: 200px" |
| | | placeholder="请输入名称" |
| | | @on-click-search="getList" |
| | | @keyup.enter="getList()" |
| | | > |
| | | </SearchInput> |
| | | </QueryFilterItem> |
| | | </template> |
| | | <template #btn> |
| | | <el-button |
| | | v-if="checkSubModuleItemShow('pageButton', 'addBtn')" |
| | | @click="openDialog()" |
| | | icon="Plus" |
| | | type="primary" |
| | | >新增</el-button |
| | | > |
| | | </template> |
| | | </ProTableQueryFilterBar> |
| | | <ProTableV2 v-bind="proTableProps" :columns="column" :operationBtns="operationBtns"> |
| | | <template #columns="{ row, column }"> |
| | | <template v-if="column.property === 'status'"> |
| | | <FieldSwitch |
| | | v-model="row.status" |
| | | active-text="显示" |
| | | inactive-text="隐藏" |
| | | :before-change="() => setCategoryVis(row)" |
| | | /> |
| | | </template> |
| | | </template> |
| | | </ProTableV2> |
| | | </AppContainer> |
| | | <AddOrEditSearchSetting v-bind="dialogProps" :typeList="typeList" /> |
| | | </LoadingLayout> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { |
| | | ProTableQueryFilterBar, |
| | | OperationBtnType, |
| | | ProTableV2, |
| | | SearchInput, |
| | | LoadingLayout, |
| | | AppContainer, |
| | | QueryFilterItem, |
| | | useTable, |
| | | useFormDialog, |
| | | UploadUserFile, |
| | | FieldSwitch, |
| | | FieldSelect, |
| | | FieldRadio, |
| | | } from '@bole-core/components'; |
| | | import { useAccess } from '@/hooks'; |
| | | import * as searchSettingServices from '@/services/api/SearchSetting'; |
| | | import { |
| | | SearchType, |
| | | SearchTypeText, |
| | | // BelongType, |
| | | // BelongTypeText, |
| | | BooleanOptions, |
| | | } from '@/constants'; |
| | | import { OrderInputType, Message } from '@bole-core/core'; |
| | | import AddOrEditSearchSetting from './components/AddOrEditSearchSetting.vue'; |
| | | import { convertApi2FormUrl } from '@/utils'; |
| | | import { useQueryClient } from '@tanstack/vue-query'; |
| | | import { useSearchSettingType } from '@/hooks'; |
| | | |
| | | defineOptions({ |
| | | name: 'SearchSetting', |
| | | }); |
| | | |
| | | const operationBtnMap: Record<string, OperationBtnType> = { |
| | | editBtn: { emits: { onClick: (role) => openDialog(role) } }, |
| | | }; |
| | | |
| | | const { checkSubModuleItemShow, column, operationBtns } = useAccess({ |
| | | operationBtnMap, |
| | | }); |
| | | |
| | | const BaseState = { |
| | | loading: true, |
| | | }; |
| | | const queryClient = useQueryClient(); |
| | | const { searchSettingTypeList: typeList } = useSearchSettingType({ |
| | | searchType: SearchType.IndustryCategory, |
| | | }); |
| | | const state = reactive({ ...BaseState }); |
| | | |
| | | onMounted(async () => { |
| | | await getList(); |
| | | state.loading = false; |
| | | }); |
| | | |
| | | const { |
| | | getDataSource: getList, |
| | | proTableProps, |
| | | paginationState, |
| | | extraParamState, |
| | | reset, |
| | | } = useTable( |
| | | async ({ pageIndex, pageSize }, extraParamState) => { |
| | | try { |
| | | let params: API.GetSearchSettingListInput = { |
| | | pageModel: { |
| | | rows: pageSize, |
| | | page: pageIndex, |
| | | orderInput: extraParamState.orderInput, |
| | | }, |
| | | name: extraParamState.name, |
| | | // belongType: Number(extraParamState.belongType), |
| | | searchType: Number(extraParamState.searchType), |
| | | status: extraParamState.status, |
| | | }; |
| | | |
| | | if (extraParamState.searchType === SearchType.Position) { |
| | | params.isRecommend = extraParamState.isRecommend; |
| | | params.parentId = extraParamState.parentId; |
| | | } |
| | | let res = await searchSettingServices.getSearchSettingList(params, { |
| | | showLoading: !state.loading, |
| | | }); |
| | | return res; |
| | | } catch (error) { |
| | | console.log('error: ', error); |
| | | } |
| | | }, |
| | | { |
| | | defaultExtraParams: { |
| | | name: '', |
| | | searchType: SearchType.Identity, |
| | | orderInput: [{ property: 'sort', order: OrderInputType.Asc }], |
| | | status: '' as any as boolean, |
| | | isRecommend: '' as any as boolean, |
| | | parentId: '', |
| | | }, |
| | | queryKey: ['searchSettingServices/getSearchSettingList'], |
| | | columnsRenderProps: { |
| | | searchType: { type: 'enum', valueEnum: SearchTypeText }, |
| | | }, |
| | | } |
| | | ); |
| | | |
| | | function openDialog(row?: API.GetSearchSettingList) { |
| | | if (row) { |
| | | handleEdit({ |
| | | id: row.id, |
| | | searchType: extraParamState.searchType, |
| | | name: row.name, |
| | | sort: row.sort, |
| | | status: row.status, |
| | | src: row.src?.length ? [convertApi2FormUrl(row.src)] : [], |
| | | parentId: row.parentId ?? '', |
| | | }); |
| | | } else { |
| | | handleAdd({ |
| | | searchType: extraParamState.searchType, |
| | | }); |
| | | } |
| | | } |
| | | |
| | | const { dialogProps, handleAdd, handleEdit, editForm, dialogState } = useFormDialog({ |
| | | onConfirm: handleAddOrEdit, |
| | | defaultFormParams: { |
| | | id: '', |
| | | searchType: SearchType.Identity, |
| | | name: '', |
| | | sort: 0, |
| | | status: true, |
| | | src: [] as UploadUserFile[], |
| | | parentId: '', |
| | | }, |
| | | }); |
| | | |
| | | async function handleAddOrEdit() { |
| | | try { |
| | | let params: API.CreateOrEditSearchInput = { |
| | | searchType: extraParamState.searchType, |
| | | name: editForm.name, |
| | | sort: editForm.sort, |
| | | status: editForm.status, |
| | | src: editForm.src?.[0]?.path ?? '', |
| | | parentId: editForm.parentId ?? '', |
| | | }; |
| | | if (editForm.id) { |
| | | params.id = editForm.id; |
| | | } |
| | | let res = await searchSettingServices.createOrEditSearchSetting(params); |
| | | if (res) { |
| | | Message.successMessage('操作成功'); |
| | | getList(paginationState.pageIndex); |
| | | dialogState.dialogVisible = false; |
| | | updateCategoryMenu(); |
| | | } |
| | | } catch (error) {} |
| | | } |
| | | |
| | | function updateCategoryMenu() { |
| | | queryClient.invalidateQueries({ |
| | | queryKey: [ |
| | | 'searchSettingServices/getTypeSearchSettingList', |
| | | { searchType: extraParamState.searchType, belongType: null }, |
| | | ], |
| | | }); |
| | | } |
| | | |
| | | async function setCategoryVis(row: API.GetSearchSettingList) { |
| | | try { |
| | | let params: API.EnableSearchSettingInput = { |
| | | id: row.id, |
| | | status: !row.status, |
| | | }; |
| | | let res = await searchSettingServices.enableSearchSetting(params); |
| | | updateCategoryMenu(); |
| | | getList(paginationState.pageIndex); |
| | | return !!res; |
| | | } catch (error) {} |
| | | } |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <ProDialog |
| | | :title="innerForm.title" |
| | | v-model="innerVisible" |
| | | @close="onDialogClose" |
| | | destroy-on-close |
| | | draggable |
| | | > |
| | | <ProForm :rules="rules" :model="innerForm" ref="dialogForm" label-width="90px"> |
| | | <ProFormItemV2 label="行业类型:" prop="parentId" v-if="showWorkSearchType"> |
| | | <ProFormSelect |
| | | v-model="innerForm.parentId" |
| | | :value-enum="typeList" |
| | | enum-value-key="id" |
| | | enum-label-key="name" |
| | | /> |
| | | </ProFormItemV2> |
| | | <ProFormItemV2 label="名称:" prop="name"> |
| | | <ProFormText |
| | | placeholder="请输入名称" |
| | | v-model.trim="innerForm.name" |
| | | :maxlength="15" |
| | | ></ProFormText> |
| | | </ProFormItemV2> |
| | | <ProFormItemV2 label="排序:" prop="sort" required> |
| | | <ProFormInputNumber |
| | | v-model="innerForm.sort" |
| | | :controls="false" |
| | | :min="0" |
| | | :max="999" |
| | | ></ProFormInputNumber> |
| | | </ProFormItemV2> |
| | | <ProFormItemV2 |
| | | label="类别图标:" |
| | | prop="src" |
| | | :check-rules="[{ type: 'upload', required: false }]" |
| | | > |
| | | <ProFormImageUpload |
| | | v-model:file-url="innerForm.src" |
| | | :limitFileCount="1" |
| | | ></ProFormImageUpload> |
| | | </ProFormItemV2> |
| | | <ProFormItemV2 label="状态:" prop="status" required> |
| | | <el-radio-group v-model="innerForm.status"> |
| | | <el-radio-button :value="true">显示</el-radio-button> |
| | | <el-radio-button :value="false">隐藏</el-radio-button> |
| | | </el-radio-group> |
| | | </ProFormItemV2> |
| | | </ProForm> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="emit('onCancel')">取 消</el-button> |
| | | <el-button type="primary" @click="handleConfirm">确 定</el-button> |
| | | </span> |
| | | </template> |
| | | </ProDialog> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { FormRules, FormInstance } from 'element-plus'; |
| | | import { SearchType } from '@/constants'; |
| | | import { |
| | | ProDialog, |
| | | ProForm, |
| | | ProFormItemV2, |
| | | ProFormRadio, |
| | | ProFormText, |
| | | ProFormInputNumber, |
| | | ProFormImageUpload, |
| | | UploadUserFile, |
| | | ProFormSelect, |
| | | } from '@bole-core/components'; |
| | | |
| | | defineOptions({ |
| | | name: 'AddOrEditSearchSetting', |
| | | }); |
| | | |
| | | type Props = { |
| | | modelValue: boolean; |
| | | form?: { |
| | | title?: string; |
| | | searchType: number; |
| | | name: string; |
| | | sort: number; |
| | | status: boolean; |
| | | src: UploadUserFile[]; |
| | | parentId?: string; |
| | | }; |
| | | typeList: API.GetTypeSearchSettingList[]; |
| | | }; |
| | | |
| | | const props = withDefaults(defineProps<Props>(), { |
| | | modelValue: false, |
| | | }); |
| | | |
| | | const showWorkSearchType = computed(() => props.form.searchType === SearchType.Position); |
| | | |
| | | const emit = defineEmits<{ |
| | | (e: 'update:modelValue', value: boolean): void; |
| | | (e: 'update:form', value: Props['form']): void; |
| | | (e: 'onConfirm'): void; |
| | | (e: 'onCancel'): void; |
| | | }>(); |
| | | |
| | | const dialogForm = ref<FormInstance>(); |
| | | |
| | | const innerVisible = computed({ |
| | | get() { |
| | | return props.modelValue; |
| | | }, |
| | | set(val) { |
| | | emit('update:modelValue', val); |
| | | }, |
| | | }); |
| | | |
| | | const innerForm = computed({ |
| | | get() { |
| | | return props.form; |
| | | }, |
| | | set(val) { |
| | | emit('update:form', val); |
| | | }, |
| | | }); |
| | | |
| | | const rules = reactive<FormRules>({ |
| | | status: [{ required: true, message: '请选择状态', trigger: 'change' }], |
| | | name: [{ required: true, message: '请输入名称', trigger: 'blur' }], |
| | | sort: [{ required: true, message: '请输入排序', trigger: 'blur' }], |
| | | parentId: [{ required: true, message: '请选择所属类别', trigger: 'change' }], |
| | | }); |
| | | |
| | | function onDialogClose() { |
| | | if (!dialogForm.value) return; |
| | | dialogForm.value.resetFields(); |
| | | } |
| | | |
| | | function handleConfirm() { |
| | | if (!dialogForm.value) return; |
| | | dialogForm.value.validate((valid) => { |
| | | if (valid) { |
| | | emit('onConfirm'); |
| | | } else { |
| | | return; |
| | | } |
| | | }); |
| | | } |
| | | </script> |