Sfoglia il codice sorgente

1、增加ThrowBah异常处理 2、同步升级vben UI框架

zuohuaijun 3 anni fa
parent
commit
b5c7ceb23a

+ 6 - 6
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -20,17 +20,17 @@
 
   <ItemGroup>
     <PackageReference Include="Caching.CSRedis" Version="3.8.3" />
-    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="3.7.8" />
-    <PackageReference Include="Furion.Extras.Logging.Serilog" Version="3.7.8" />
-    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="3.7.8" />
-    <PackageReference Include="Furion.Pure" Version="3.7.8" />
+    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="3.7.11" />
+    <PackageReference Include="Furion.Extras.Logging.Serilog" Version="3.7.11" />
+    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="3.7.11" />
+    <PackageReference Include="Furion.Pure" Version="3.7.11" />
     <PackageReference Include="Magicodes.IE.Excel" Version="2.6.4" />
     <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.6" />
     <PackageReference Include="MySql.Data" Version="8.0.29" />
-    <PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.1.5" />
+    <PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.1.6" />
     <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="2.16.0" />
     <PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="2.11.0" />
-    <PackageReference Include="SqlSugarCore" Version="5.0.9.2" />
+    <PackageReference Include="SqlSugarCore" Version="5.0.9.4" />
     <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.19" />
     <PackageReference Include="UAParser" Version="3.1.47" />
     <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />

+ 4 - 0
Admin.NET/Admin.NET.Core/AdminNETConfig.json

@@ -27,6 +27,10 @@
     "KeepName": true,
     "AsLowerCamelCase": true // 小驼峰路由路径
   },
+  "FriendlyExceptionSettings": {
+    "DefaultErrorMessage": "系统异常,请联系管理员",
+    "ThrowBah": true
+  },
   "JWTSettings": {
     "ValidateIssuerSigningKey": true, // 是否验证密钥,bool 类型,默认true
     "IssuerSigningKey": "3c1cbc3f546eda35168c3aa3cb91780fbe703f0996c6d123ea96dc85c70bbc0a", // 密钥,string 类型,必须是复杂密钥,长度大于16

+ 3 - 4
Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs

@@ -61,12 +61,11 @@ public static class SqlSugarSetup
                     // 新增操作
                     if (entityInfo.OperationType == DataFilterType.InsertByObject)
                     {
-                        // 主键(long类型)-赋值雪花Id
+                        // 主键(long类型)且没有值的---赋值雪花Id
                         if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
                         {
-                            var keyId = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
-                            //默认有id,则不用生成,有些业务需要提前设置id
-                            if (keyId == null || (long)keyId == 0)
+                            var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
+                            if (id == null || (long)id == 0)
                                 entityInfo.SetValue(Yitter.IdGenerator.YitIdHelper.NextId());
                         }
                         if (entityInfo.PropertyName == "CreateTime")

+ 74 - 0
Vben2/commitlint.config.js

@@ -1,3 +1,23 @@
+const fs = require('fs');
+const path = require('path');
+const { execSync } = require('child_process');
+
+const scopes = fs
+  .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })
+  .filter((dirent) => dirent.isDirectory())
+  .map((dirent) => dirent.name.replace(/s$/, ''));
+
+// precomputed scope
+const scopeComplete = execSync('git status --porcelain || true')
+  .toString()
+  .trim()
+  .split('\n')
+  .find((r) => ~r.indexOf('M  src'))
+  ?.replace(/(\/)/g, '%%')
+  ?.match(/src%%((\w|-)*)/)?.[1]
+  ?.replace(/s$/, '');
+
+/** @type {import('cz-git').UserConfig} */
 module.exports = {
   ignores: [(commit) => commit.includes('init')],
   extends: ['@commitlint/config-conventional'],
@@ -30,4 +50,58 @@ module.exports = {
       ],
     ],
   },
+  prompt: {
+    /** @use `yarn commit :f` */
+    alias: {
+      f: 'docs: fix typos',
+      r: 'docs: update README',
+      s: 'style: update code format',
+      b: 'build: bump dependencies',
+      c: 'chore: update config',
+    },
+    customScopesAlign: !scopeComplete ? 'top' : 'bottom',
+    defaultScope: scopeComplete,
+    scopes: [...scopes, 'mock'],
+    allowEmptyIssuePrefixs: false,
+    allowCustomIssuePrefixs: false,
+
+    // English
+    typesAppend: [
+      { value: 'wip', name: 'wip:      work in process' },
+      { value: 'workflow', name: 'workflow: workflow improvements' },
+      { value: 'types', name: 'types:    type definition file changes' },
+    ],
+
+    // 中英文对照版
+    // messages: {
+    //   type: '选择你要提交的类型 :',
+    //   scope: '选择一个提交范围 (可选):',
+    //   customScope: '请输入自定义的提交范围 :',
+    //   subject: '填写简短精炼的变更描述 :\n',
+    //   body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
+    //   breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
+    //   footerPrefixsSelect: '选择关联issue前缀 (可选):',
+    //   customFooterPrefixs: '输入自定义issue前缀 :',
+    //   footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
+    //   confirmCommit: '是否提交或修改commit ?',
+    // },
+    // types: [
+    //   { value: 'feat', name: 'feat:     新增功能' },
+    //   { value: 'fix', name: 'fix:      修复缺陷' },
+    //   { value: 'docs', name: 'docs:     文档变更' },
+    //   { value: 'style', name: 'style:    代码格式' },
+    //   { value: 'refactor', name: 'refactor: 代码重构' },
+    //   { value: 'perf', name: 'perf:     性能优化' },
+    //   { value: 'test', name: 'test:     添加疏漏测试或已有测试改动' },
+    //   { value: 'build', name: 'build:    构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
+    //   { value: 'ci', name: 'ci:       修改 CI 配置、脚本' },
+    //   { value: 'revert', name: 'revert:   回滚 commit' },
+    //   { value: 'chore', name: 'chore:    对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
+    //   { value: 'wip', name: 'wip:      正在开发中' },
+    //   { value: 'workflow', name: 'workflow: 工作流程改进' },
+    //   { value: 'types', name: 'types:    类型定义文件修改' },
+    // ],
+    // emptyScopesAlias: 'empty:      不填写',
+    // customScopesAlias: 'custom:     自定义',
+  },
 };

+ 9 - 7
Vben2/mock/_util.ts

@@ -1,8 +1,9 @@
 // Interface data format used to return a unified format
+import { ResultEnum } from '/@/enums/httpEnum';
 
 export function resultSuccess<T = Recordable>(result: T, { message = 'ok' } = {}) {
   return {
-    code: 0,
+    code: ResultEnum.SUCCESS,
     result,
     message,
     type: 'success',
@@ -26,7 +27,10 @@ export function resultPageSuccess<T = any>(
   };
 }
 
-export function resultError(message = 'Request failed', { code = -1, result = null } = {}) {
+export function resultError(
+  message = 'Request failed',
+  { code = ResultEnum.ERROR, result = null } = {},
+) {
   return {
     code,
     result,
@@ -37,11 +41,9 @@ export function resultError(message = 'Request failed', { code = -1, result = nu
 
 export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] {
   const offset = (pageNo - 1) * Number(pageSize);
-  const ret =
-    offset + Number(pageSize) >= array.length
-      ? array.slice(offset, array.length)
-      : array.slice(offset, offset + Number(pageSize));
-  return ret;
+  return offset + Number(pageSize) >= array.length
+    ? array.slice(offset, array.length)
+    : array.slice(offset, offset + Number(pageSize));
 }
 
 export interface requestParams {

+ 8 - 1
Vben2/package.json

@@ -7,6 +7,7 @@
     "url": "https://github.com/anncwb"
   },
   "scripts": {
+    "commit": "czg",
     "bootstrap": "pnpm install",
     "serve": "npm run dev",
     "dev": "vite",
@@ -96,9 +97,10 @@
     "@vue/compiler-sfc": "^3.2.33",
     "@vue/test-utils": "^2.0.0-rc.21",
     "autoprefixer": "^10.4.4",
-    "commitizen": "^4.2.4",
     "conventional-changelog-cli": "^2.2.2",
     "cross-env": "^7.0.3",
+    "cz-git": "^1.3.9",
+    "czg": "^1.3.9",
     "dotenv": "^16.0.0",
     "eslint": "^8.13.0",
     "eslint-config-prettier": "^8.5.0",
@@ -183,5 +185,10 @@
     "*.md": [
       "prettier --write"
     ]
+  },
+  "config": {
+    "commitizen": {
+      "path": "node_modules/cz-git"
+    }
   }
 }

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

@@ -12,5 +12,6 @@ export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue';
 export { default as ApiTree } from './src/components/ApiTree.vue';
 export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue';
 export { default as ApiCascader } from './src/components/ApiCascader.vue';
+export { default as ApiTransfer } from './src/components/ApiTransfer.vue';
 
 export { BasicForm };

+ 2 - 0
Vben2/src/components/Form/src/componentMap.ts

@@ -27,6 +27,7 @@ import ApiSelect from './components/ApiSelect.vue';
 import ApiTree from './components/ApiTree.vue';
 import ApiTreeSelect from './components/ApiTreeSelect.vue';
 import ApiCascader from './components/ApiCascader.vue';
+import ApiTransfer from './components/ApiTransfer.vue';
 import { BasicUpload } from '/@/components/Upload';
 import { StrengthMeter } from '/@/components/StrengthMeter';
 import { IconPicker } from '/@/components/Icon';
@@ -57,6 +58,7 @@ componentMap.set('ApiCascader', ApiCascader);
 componentMap.set('Cascader', Cascader);
 componentMap.set('Slider', Slider);
 componentMap.set('Rate', Rate);
+componentMap.set('ApiTransfer', ApiTransfer);
 
 componentMap.set('DatePicker', DatePicker);
 componentMap.set('MonthPicker', DatePicker.MonthPicker);

+ 135 - 0
Vben2/src/components/Form/src/components/ApiTransfer.vue

@@ -0,0 +1,135 @@
+<template>
+  <Transfer
+    :data-source="getdataSource"
+    show-search
+    :filter-option="filterOption"
+    :render="(item) => item.title"
+    :showSelectAll="showSelectAll"
+    :selectedKeys="selectedKeys"
+    :targetKeys="getTargetKeys"
+    :showSearch="showSearch"
+    @change="handleChange"
+  />
+</template>
+
+<script lang="ts">
+  import { computed, defineComponent, watch, ref, unref, watchEffect } from 'vue';
+  import { Transfer } from 'ant-design-vue';
+  import { isFunction } from '/@/utils/is';
+  import { get, omit } from 'lodash-es';
+  import { propTypes } from '/@/utils/propTypes';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { TransferDirection, TransferItem } from 'ant-design-vue/lib/transfer';
+  export default defineComponent({
+    name: 'ApiTransfer',
+    components: { Transfer },
+    props: {
+      value: { type: Array<string> },
+      api: {
+        type: Function as PropType<(arg?: Recordable) => Promise<TransferItem[]>>,
+        default: null,
+      },
+      params: { type: Object },
+      dataSource: { type: Array<TransferItem> },
+      immediate: propTypes.bool.def(true),
+      alwaysLoad: propTypes.bool.def(false),
+      afterFetch: { type: Function as PropType<Fn> },
+      resultField: propTypes.string.def(''),
+      labelField: propTypes.string.def('title'),
+      valueField: propTypes.string.def('key'),
+      showSearch: { type: Boolean, default: false },
+      disabled: { type: Boolean, default: false },
+      filterOption: {
+        type: Function as PropType<(inputValue: string, item: TransferItem) => boolean>,
+      },
+      selectedKeys: { type: Array<string> },
+      showSelectAll: { type: Boolean, default: false },
+      targetKeys: { type: Array<string> },
+    },
+    emits: ['options-change', 'change'],
+    setup(props, { attrs, emit }) {
+      const _dataSource = ref<TransferItem[]>([]);
+      const _targetKeys = ref<string[]>([]);
+      const { t } = useI18n();
+
+      const getAttrs = computed(() => {
+        return {
+          ...(!props.api ? { dataSource: unref(_dataSource) } : {}),
+          ...attrs,
+        };
+      });
+      const getdataSource = computed(() => {
+        const { labelField, valueField } = props;
+
+        return unref(_dataSource).reduce((prev, next: Recordable) => {
+          if (next) {
+            prev.push({
+              ...omit(next, [labelField, valueField]),
+              title: next[labelField],
+              key: next[valueField],
+            });
+          }
+          return prev;
+        }, [] as TransferItem[]);
+      });
+      const getTargetKeys = computed<string[]>(() => {
+        if (unref(_targetKeys).length > 0) {
+          return unref(_targetKeys);
+        }
+        if (Array.isArray(props.value)) {
+          return props.value;
+        }
+        return [];
+      });
+
+      function handleChange(keys: string[], direction: TransferDirection, moveKeys: string[]) {
+        _targetKeys.value = keys;
+        console.log(direction);
+        console.log(moveKeys);
+        emit('change', keys);
+      }
+
+      watchEffect(() => {
+        props.immediate && !props.alwaysLoad && fetch();
+      });
+
+      watch(
+        () => props.params,
+        () => {
+          fetch();
+        },
+        { deep: true },
+      );
+
+      async function fetch() {
+        const api = props.api;
+        if (!api || !isFunction(api)) {
+          if (Array.isArray(props.dataSource)) {
+            _dataSource.value = props.dataSource;
+          }
+          return;
+        }
+        _dataSource.value = [];
+        try {
+          const res = await api(props.params);
+          if (Array.isArray(res)) {
+            _dataSource.value = res;
+            emitChange();
+            return;
+          }
+          if (props.resultField) {
+            _dataSource.value = get(res, props.resultField) || [];
+          }
+          emitChange();
+        } catch (error) {
+          console.warn(error);
+        } finally {
+        }
+      }
+      function emitChange() {
+        emit('options-change', unref(getdataSource));
+      }
+      return { getTargetKeys, getdataSource, t, getAttrs, handleChange };
+    },
+  });
+</script>

+ 2 - 1
Vben2/src/components/Form/src/types/index.ts

@@ -113,4 +113,5 @@ export type ComponentType =
   | 'Render'
   | 'Slider'
   | 'Rate'
-  | 'Divider';
+  | 'Divider'
+  | 'ApiTransfer';

+ 1 - 1
Vben2/src/components/Table/src/hooks/useTableScroll.ts

@@ -191,7 +191,7 @@ export function useTableScroll(
 
     const columns = unref(columnsRef).filter((item) => !item.defaultHidden);
     columns.forEach((item) => {
-      width += Number.parseInt(item.width as string) || 0;
+      width += Number.parseFloat(item.width as string) || 0;
     });
     const unsetWidthColumns = columns.filter((item) => !Reflect.has(item, 'width'));
 

+ 7 - 0
Vben2/src/design/ant/input.less

@@ -22,3 +22,10 @@
     padding: 4px;
   }
 }
+
+.ant-input-number {
+  width: 100% !important;
+  max-width: 100%;
+}
+
+

+ 6 - 2
Vben2/src/layouts/page/index.vue

@@ -15,9 +15,13 @@
         appear
       >
         <keep-alive v-if="openCache" :include="getCaches">
-          <component :is="Component" :key="route.fullPath" />
+          <div :key="route.name">
+            <component :is="Component" :key="route.fullPath" />
+          </div>
         </keep-alive>
-        <component v-else :is="Component" :key="route.fullPath" />
+        <div v-else :key="route.name">
+          <component :is="Component" :key="route.fullPath" />
+        </div>
       </transition>
     </template>
   </RouterView>

+ 19 - 0
Vben2/src/locales/lang/zh-CN/antdLocale/DatePicker.ts

@@ -0,0 +1,19 @@
+export default {
+  lang: {
+    shortWeekDays: ['一', '二', '三', '四', '五', '六', '日'],
+    shortMonths: [
+      '1月',
+      '2月',
+      '3月',
+      '4月',
+      '5月',
+      '6月',
+      '7月',
+      '8月',
+      '9月',
+      '10月',
+      '11月',
+      '12月',
+    ],
+  },
+};

+ 1 - 1
Vben2/src/utils/helper/tsxHelper.tsx

@@ -29,7 +29,7 @@ export function extendSlots(slots: Slots, excludeKeys: string[] = []) {
     if (excludeKeys.includes(key)) {
       return null;
     }
-    ret[key] = () => getSlot(slots, key);
+    ret[key] = (data?: any) => getSlot(slots, key, data);
   });
   return ret;
 }