From c3207c8517780ec2019bd1e0943a62cc29b265d0 Mon Sep 17 00:00:00 2001
From: zhengyiming <540361168@qq.com>
Date: 星期二, 18 二月 2025 14:58:32 +0800
Subject: [PATCH] feat: api

---
 src/constants/dic.ts                                             |   23 ++
 src/hooks/dic.ts                                                 |   55 ++++++
 src/services/api/typings.d.ts                                    |    1 
 src/constants/enum.ts                                            |    5 
 src/constants/index.ts                                           |    1 
 src/views/DictionaryManage/SearchSetting.vue                     |  244 ++++++++++++++++++++++++++++++
 src/hooks/index.ts                                               |    1 
 src/views/DictionaryManage/components/AddOrEditSearchSetting.vue |  147 ++++++++++++++++++
 src/utils/request/index.ts                                       |    1 
 9 files changed, 477 insertions(+), 1 deletions(-)

diff --git a/src/constants/dic.ts b/src/constants/dic.ts
new file mode 100644
index 0000000..3ad3406
--- /dev/null
+++ b/src/constants/dic.ts
@@ -0,0 +1,23 @@
+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]: '琛屼笟绫诲瀷',
+};
diff --git a/src/constants/enum.ts b/src/constants/enum.ts
index 936694e..e403f0e 100644
--- a/src/constants/enum.ts
+++ b/src/constants/enum.ts
@@ -38,3 +38,8 @@
   Role = 1,
   User,
 }
+
+export const BooleanOptions = [
+  { label: '鏄�', value: true },
+  { label: '鍚�', value: false },
+];
diff --git a/src/constants/index.ts b/src/constants/index.ts
index fa61beb..303e5a6 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -9,3 +9,4 @@
 export * from './menu';
 export * from './role';
 export * from './app';
+export * from './dic';
diff --git a/src/hooks/dic.ts b/src/hooks/dic.ts
new file mode 100644
index 0000000..d55c72f
--- /dev/null
+++ b/src/hooks/dic.ts
@@ -0,0 +1,55 @@
+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,
+  };
+}
diff --git a/src/hooks/index.ts b/src/hooks/index.ts
index cbe1cbd..bc2b519 100644
--- a/src/hooks/index.ts
+++ b/src/hooks/index.ts
@@ -6,3 +6,4 @@
 export * from './useEvent';
 export * from './useUser';
 export * from './help';
+export * from './dic';
diff --git a/src/services/api/typings.d.ts b/src/services/api/typings.d.ts
index efb90c7..cd366cf 100644
--- a/src/services/api/typings.d.ts
+++ b/src/services/api/typings.d.ts
@@ -713,6 +713,7 @@
     clickCount?: number;
     src?: string;
     isRecommend?: boolean;
+    searchType?: number;
   }
 
   interface GetSearchSettingListInput {
diff --git a/src/utils/request/index.ts b/src/utils/request/index.ts
index 3c654d4..3ebb819 100644
--- a/src/utils/request/index.ts
+++ b/src/utils/request/index.ts
@@ -170,7 +170,6 @@
   requestInterceptors: [
     [
       (config) => {
-        console.log('req config: ', config);
         const $config = config;
         // 寮�鍚繘搴︽潯鍔ㄧ敾
         if (config.needNProcess) {
diff --git a/src/views/DictionaryManage/SearchSetting.vue b/src/views/DictionaryManage/SearchSetting.vue
new file mode 100644
index 0000000..a23b025
--- /dev/null
+++ b/src/views/DictionaryManage/SearchSetting.vue
@@ -0,0 +1,244 @@
+<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>
diff --git a/src/views/DictionaryManage/components/AddOrEditSearchSetting.vue b/src/views/DictionaryManage/components/AddOrEditSearchSetting.vue
new file mode 100644
index 0000000..1eab56d
--- /dev/null
+++ b/src/views/DictionaryManage/components/AddOrEditSearchSetting.vue
@@ -0,0 +1,147 @@
+<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>

--
Gitblit v1.9.1