Quellcode durchsuchen

系统配置优化。。。

wangwei vor 3 Jahren
Ursprung
Commit
e637e8c6e3

+ 2 - 1
src/components/Form/src/componentMap.ts

@@ -24,6 +24,7 @@ import FamilyArrCom from './components/FamilyArrCom.vue';
 import CarArrayCom from './components/CarArrayCom.vue';
 import RangeNumber from './components/RangeNumber.vue';
 import ApiSelect from './components/ApiSelect.vue';
+import GroupApiSelect from './components/GroupApiSelect.vue';
 import UploadFile from './components/upload/UploadFile.vue';
 import UploadImage from './components/upload/UploadImage.vue';
 import { BasicUpload } from '/@/components/Upload';
@@ -41,6 +42,7 @@ componentMap.set('RangeNumber', RangeNumber);
 componentMap.set('AutoComplete', AutoComplete);
 
 componentMap.set('Select', Select);
+componentMap.set('GroupApiSelect', GroupApiSelect);
 componentMap.set('ApiSelect', ApiSelect);
 componentMap.set('FamilyArrCom', FamilyArrCom);
 componentMap.set('CarArrayCom', CarArrayCom);
@@ -58,7 +60,6 @@ componentMap.set('RadioGroup', Radio.Group);
 componentMap.set('Checkbox', Checkbox);
 componentMap.set('CheckboxGroup', Checkbox.Group);
 componentMap.set('Cascader', Cascader);
-
 componentMap.set('DatePicker', DatePicker);
 componentMap.set('MonthPicker', DatePicker.MonthPicker);
 componentMap.set('RangePicker', DatePicker.RangePicker);

+ 1 - 1
src/components/Form/src/components/ApiSelect.vue

@@ -72,7 +72,7 @@
       const { t } = useI18n();
 
       // Embedded in the form, just use the hook binding to perform form verification
-      const [state] = useRuleFormItem(props);
+      const [state] = useRuleFormItem(props) as any;
 
       const getOptions = computed(() => {
         const { labelField, valueField, numberToString } = props;

+ 147 - 0
src/components/Form/src/components/GroupApiSelect.vue

@@ -0,0 +1,147 @@
+<template>
+  <Select
+    @dropdownVisibleChange="handleFetch"
+    v-bind="attrs"
+    :options="getOptions"
+    v-model:value="state"
+  >
+    <template #[item]="data" v-for="item in Object.keys($slots)">
+      <slot :name="item" v-bind="data"></slot>
+    </template>
+    <template #suffixIcon v-if="loading">
+      <LoadingOutlined spin />
+    </template>
+    <template #notFoundContent v-if="loading">
+      <span>
+        <LoadingOutlined spin class="mr-1" />
+        {{ t('component.form.apiSelectNotFound') }}
+      </span>
+    </template>
+  </Select>
+</template>
+<script lang="ts">
+  import { defineComponent, PropType, ref, watchEffect, computed, unref, watch } from 'vue';
+  import { Select } from 'ant-design-vue';
+  import { isFunction } from '/@/utils/is';
+  import { useRuleFormItem } from '/@/hooks/component/useFormItem';
+  import { useAttrs } from '/@/hooks/core/useAttrs';
+  import { get, omit } from 'lodash-es';
+
+  import { LoadingOutlined } from '@ant-design/icons-vue';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { propTypes } from '/@/utils/propTypes';
+
+  type OptionsItem = { label: string; value: string; disabled?: boolean };
+
+  export default defineComponent({
+    name: 'GroupApiSelect',
+    components: {
+      Select,
+      LoadingOutlined,
+    },
+    inheritAttrs: false,
+    props: {
+      value: propTypes.oneOfType([
+        propTypes.object,
+        propTypes.number,
+        propTypes.string,
+        propTypes.array,
+      ]),
+      numberToString: propTypes.bool,
+      api: {
+        type: Function as PropType<(arg?: Recordable) => Promise<OptionsItem[]>>,
+        default: null,
+      },
+      // api params
+      params: {
+        type: Object as PropType<Recordable>,
+        default: () => ({}),
+      },
+      // support xxx.xxx.xx
+      resultField: propTypes.string.def(''),
+      labelField: propTypes.string.def('label'),
+      valueField: propTypes.string.def('value'),
+      immediate: propTypes.bool.def(true),
+    },
+    emits: ['options-change', 'change'],
+    setup(props, { emit }) {
+      const options = ref<OptionsItem[]>([]);
+      const loading = ref(false);
+      const isFirstLoad = ref(true);
+      const attrs = useAttrs();
+      const { t } = useI18n();
+
+      // Embedded in the form, just use the hook binding to perform form verification
+      const [state] = useRuleFormItem(props) as any;
+
+      const getOptions = computed(() => {
+        const { labelField, valueField, numberToString } = props;
+
+        return unref(options).reduce((prev, next: Recordable) => {
+          if (next) {
+            const value = next[valueField];
+            prev.push({
+              label: next[labelField],
+              value: numberToString ? `${value}` : value,
+              ...omit(next, [labelField, valueField]),
+            });
+          }
+          return prev;
+        }, [] as OptionsItem[]);
+      });
+
+      watchEffect(() => {
+        props.immediate && fetch();
+      });
+
+      watch(
+        () => props.params,
+        () => {
+          !unref(isFirstLoad) && fetch();
+        },
+        { deep: true }
+      );
+
+      async function fetch() {
+        const api = props.api;
+        if (!api || !isFunction(api)) return;
+
+        try {
+          loading.value = true;
+          const result: any = await api(props.params);
+          const res: OptionsItem[] = [];
+          Object.keys(result.group).map((item: string) => {
+            res.push({ label: result.group[item], value: item });
+          });
+          console.log(`res`, res);
+          if (Array.isArray(res)) {
+            options.value = res;
+            emitChange();
+            return;
+          }
+          if (props.resultField) {
+            options.value = get(res, props.resultField) || [];
+          }
+          emitChange();
+        } catch (error) {
+          console.warn(error);
+        } finally {
+          loading.value = false;
+        }
+      }
+
+      async function handleFetch() {
+        if (!props.immediate && unref(isFirstLoad)) {
+          await fetch();
+          isFirstLoad.value = false;
+        }
+      }
+
+      function emitChange() {
+        emit('options-change', unref(options));
+      }
+
+      return { state, attrs, getOptions, loading, t, handleFetch };
+    },
+  });
+</script>

+ 1 - 0
src/components/Form/src/types/index.ts

@@ -96,6 +96,7 @@ export type ComponentType =
   | 'UploadFile'
   | 'UploadImage'
   | 'ApiSelect'
+  | 'GroupApiSelect'
   | 'SelectOptGroup'
   | 'TreeSelect'
   | 'MultipleTreeSelect'

+ 5 - 1
src/views/admin/rule/data.ts

@@ -50,6 +50,10 @@ export const columns: BasicColumn[] = [
     dataIndex: 'ismenu',
     width: 80,
     customRender: ({ record }) => {
+      let disabled = true;
+      if (record.ismenu) {
+        disabled = false;
+      }
       async function onChange(val) {
         console.log(val, record.id);
         record.ismenu = val;
@@ -57,7 +61,7 @@ export const columns: BasicColumn[] = [
         await editRule(data);
         reloadMenu();
       }
-      return h(Switch, { checked: record.ismenu, onChange: onChange });
+      return h(Switch, { checked: record.ismenu, disabled, onChange: onChange });
     },
   },
   {

+ 6 - 1
src/views/general/config/customComponents/ArrayCom.vue

@@ -19,7 +19,12 @@
           <Input v-model:value="item.value" @change="onChange" />
         </div>
         <a-button class="mr-2" preIcon="mdi:close-thick" color="error" @click="remove(index)" />
-        <a-button class="mr-2 drag-btn" preIcon="ri:drag-move-2-fill" type="primary" />
+        <a-button
+          v-show="false"
+          class="mr-2 drag-btn"
+          preIcon="ri:drag-move-2-fill"
+          type="primary"
+        />
       </div>
     </div>
     <a-button class="add-btn mr-2" size="small" color="success" @click="create"> 追加 </a-button>

+ 4 - 23
src/views/general/config/data.ts

@@ -16,6 +16,7 @@ import Switch from './customComponents/Switch.vue';
 import UploadImage from './customComponents/UploadImage.vue';
 import UploadFile from './customComponents/UploadFile.vue';
 import { configNameExist } from '/@/api/sys/general';
+import { getConfigGroup } from '/@/api/sys/general';
 
 export const columns: BasicColumn[] = [
   {
@@ -34,6 +35,7 @@ export const columns: BasicColumn[] = [
         case 'string':
           const onchange = (val) => {
             record.value = val;
+            console.log(`record`, record);
           };
           return h(Input, {
             value: record.value,
@@ -302,35 +304,14 @@ export const schemas: FormSchema[] = [
   },
   {
     field: 'group',
-    component: 'Select',
+    component: 'GroupApiSelect',
     label: '分组',
     colProps: {
       span: 20,
     },
     defaultValue: 'basic',
     componentProps: {
-      options: [
-        {
-          label: '基础配置',
-          value: 'basic',
-        },
-        {
-          label: '邮件配置',
-          value: 'email',
-        },
-        {
-          label: '字典配置',
-          value: 'dictionary',
-        },
-        {
-          label: '会员配置',
-          value: 'user',
-        },
-        {
-          label: '示例配置',
-          value: 'example',
-        },
-      ],
+      api: getConfigGroup,
     },
   },
   {

+ 39 - 29
src/views/general/config/index.vue

@@ -5,27 +5,31 @@
     :canExpan="false"
     helpMessage="可以在此增改系统的变量和分组,也可以自定义分组和变量"
   >
-    <a-button
-      v-for="(group, index) in groupList"
-      :key="index"
-      type="default"
-      class="mr-2"
-      :id="current_index === index ? 'current-btn' : 'static-btn'"
-      @click="handleGroupBtn(group, index)"
-    >
-      {{ group }}
-    </a-button>
-    <a-button
-      preIcon="bx:bx-plus-medical"
-      @mouseenter="showTip"
-      @mouseleave="hideTip"
-      @click="addConfig"
-      class="mr-2"
-    />
-    <span v-if="tipShow" class="tip">点击添加新的配置</span>
+    <div v-for="(group, index) in groupList" :key="index" style="display: inline-block">
+      <a-button
+        v-if="group !== 'add'"
+        type="default"
+        class="mr-2"
+        :id="current_index === index ? 'current-btn' : 'static-btn'"
+        @click="handleGroupBtn(group, index)"
+      >
+        {{ group }}
+      </a-button>
+      <a-button
+        v-else
+        type="default"
+        preIcon="bx:bx-plus-medical"
+        :id="current_index === index ? 'current-btn' : 'static-btn'"
+        @mouseenter="showTip"
+        @mouseleave="hideTip"
+        @click="addConfig(index)"
+        class="mr-2"
+      />
+    </div>
+    <span v-if="tipShow" class="tip">点击添加新的配置{{ current_index === -1 }}</span>
     <BasicTable ref="tableRef" :canResize="true" v-if="tableShow" @register="registerTable">
-      <template #action="{ record, column }">
-        <TableAction :actions="createActions(record, column)" stopButtonPropagation />
+      <template #action="{ record }">
+        <TableAction :actions="createActions(record)" stopButtonPropagation />
       </template>
     </BasicTable>
     <BasicForm
@@ -84,7 +88,7 @@
         tipShow: false,
         tableShow: true,
         formShow: false,
-        groupList: [] as object[],
+        groupList: [] as string[],
         group: 'basic',
         current_index: 0,
       });
@@ -128,19 +132,20 @@
 
       // 处理请求数据
       function afterFetch(result) {
-        result = result[state.group].list;
-        if (result[0].title === 'Site name') {
-          appStore.setAppTitle(result[0].value);
+        let res = result[state.group].list;
+        if (state.group === 'basic' && res[0].title === 'Site name') {
+          appStore.setAppTitle(res[0].value);
         }
-        if (result[1].title === 'Logo') {
-          appStore.setAppLogo(result[1].value);
+        if (state.group === 'basic' && res[1].title === 'Logo') {
+          appStore.setAppLogo(res[1].value);
         }
-        return result;
+        return res;
       }
       getGroupList();
       async function getGroupList() {
         const res = await getConfigGroup();
-        state.groupList = Object.values(res.group);
+        state.groupList = Object.values(res.group) as any;
+        state.groupList.push('add');
       }
 
       function showTip() {
@@ -160,7 +165,8 @@
         state.group = group.toLowerCase();
       }
 
-      function addConfig() {
+      function addConfig(i) {
+        state.current_index = i;
         state.tableShow = false;
         state.formShow = true;
       }
@@ -198,6 +204,10 @@
           await editConfigInfo(params).then(() => {
             getTableAction().reload();
             success('修改成功!');
+            // 修改了字典配置更新分组
+            if (state.group === 'dictionary') {
+              getGroupList();
+            }
           });
         } else {
           console.log('======未通过校验====');

+ 0 - 1
src/views/member/member/index.vue

@@ -111,7 +111,6 @@
       const [registerTable] = useTable({
         rowSelection: { type: 'checkbox' },
         columns: columns,
-        // clickToRowSelect: false, // 点击行不勾选
         api: getUserList,
         useSearchForm: true,
         beforeFetch: beforeFetch,