Authored by Bad

初始化

Showing 77 changed files with 4761 additions and 0 deletions

Too many changes to show.

To preserve performance only 77 of 77+ files are displayed.

  1 +root = true
  2 +[*.{js,ts,vue}]
  3 +charset = utf-8 # 设置文件字符集为 utf-8
  4 +end_of_line = lf # 控制换行类型(lf | cr | crlf)
  5 +insert_final_newline = true # 始终在文件末尾插入一个新行
  6 +indent_style = space # 缩进风格(tab | space)
  7 +indent_size = 2 # 缩进大小
  8 +max_line_length = 100 # 最大行长度
  9 +
  10 +[*.md] # 仅 md 文件适用以下规则
  11 +max_line_length = off # 关闭最大行长度限制
  12 +trim_trailing_whitespace = false # 关闭末尾空格修剪
  1 +# 标题
  2 +VITE_APP_TITLE=鸿星健身管理系统
  3 +
  4 +# 项目本地运行端口号
  5 +VITE_PORT=9008
  6 +
  7 +# open 运行 npm run dev 时自动打开浏览器
  8 +VITE_OPEN=true
  9 +
  10 +# 租户开关
  11 +VITE_APP_TENANT_ENABLE=false
  12 +
  13 +# 验证码的开关
  14 +VITE_APP_CAPTCHA_ENABLE=false
  15 +
  16 +# 文档地址的开关
  17 +VITE_APP_DOCALERT_ENABLE=false
  18 +
  19 +# 百度统计
  20 +VITE_APP_BAIDU_CODE = a1ff8825baa73c3a78eb96aa40325abc
  21 +
  22 +# 默认账户密码
  23 +VITE_APP_DEFAULT_LOGIN_TENANT = 芋道源码
  24 +VITE_APP_DEFAULT_LOGIN_USERNAME = admin
  25 +VITE_APP_DEFAULT_LOGIN_PASSWORD = admin123
  26 +
  27 +# API 加解密
  28 +VITE_APP_API_ENCRYPT_ENABLE = true
  29 +VITE_APP_API_ENCRYPT_HEADER = X-Api-Encrypt
  30 +VITE_APP_API_ENCRYPT_ALGORITHM = AES
  31 +VITE_APP_API_ENCRYPT_REQUEST_KEY = 52549111389893486934626385991395
  32 +VITE_APP_API_ENCRYPT_RESPONSE_KEY = 96103715984234343991809655248883
  33 +# VITE_APP_API_ENCRYPT_REQUEST_KEY = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCls2rIpnGdYnLFgz1XU13GbNQ5DloyPpvW00FPGjqn5Z6JpK+kDtVlnkhwR87iRrE5Vf2WNqRX6vzbLSgveIQY8e8oqGCb829myjf1MuI+ZzN4ghf/7tEYhZJGPI9AbfxFqBUzm+kR3/HByAI22GLT96WM26QiMK8n3tIP/yiLswIDAQAB
  34 +# VITE_APP_API_ENCRYPT_RESPONSE_KEY = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOH8IfIFxL/MR9XIg1UDv5z1fGXQI93E8wrU4iPFovL/sEt9uSgSkjyidC2O7N+m7EKtoN6b1u7cEwXSkwf3kfK0jdWLSQaNpX5YshqXCBzbDfugDaxuyYrNA4/tIMs7mzZAk0APuRXB35Dmupou7Yw7TFW/7QhQmGfzeEKULQvnAgMBAAECgYAw8LqlQGyQoPv5p3gRxEMOCfgL0JzD3XBJKztiRd35RDh40Nx1ejgjW4dPioFwGiVWd2W8cAGHLzALdcQT2KDJh+T/tsd4SPmI6uSBBK6Ff2DkO+kFFcuYvfclQQKqxma5CaZOSqhgenacmgTMFeg2eKlY3symV6JlFNu/IKU42QJBAOhxAK/Eq3e61aYQV2JSguhMR3b8NXJJRroRs/QHEanksJtl+M+2qhkC9nQVXBmBkndnkU/l2tYcHfSBlAyFySMCQQD445tgm/J2b6qMQmuUGQAYDN8FIkHjeKmha+l/fv0igWm8NDlBAem91lNDIPBUzHL1X1+pcts5bjmq99YdOnhtAkAg2J8dN3B3idpZDiQbC8fd5bGPmdI/pSUudAP27uzLEjr2qrE/QPPGdwm2m7IZFJtK7kK1hKio6u48t/bg0iL7AkEAuUUs94h+v702Fnym+jJ2CHEkXvz2US8UDs52nWrZYiM1o1y4tfSHm8H8bv8JCAa9GHyriEawfBraILOmllFdLQJAQSRZy4wmlaG48MhVXodB85X+VZ9krGXZ2TLhz7kz9iuToy53l9jTkESt6L5BfBDCVdIwcXLYgK+8KFdHN5W7HQ==
  35 +
  36 +# 百度地图
  37 +# VITE_BAIDU_MAP_KEY = 'efHIw2qmH8RzHPxK0z0rbCgzDVLup9LD'
  38 +VITE_BAIDU_MAP_KEY = 'CNSBZ-67L3W-OG6RY-3E4IM-XAQKJ-LVBTT'
  1 +# 开发环境:本地只启动前端项目,依赖开发环境(后端、APP)
  2 +NODE_ENV=production
  3 +
  4 +VITE_DEV=true
  5 +
  6 +# 请求路径
  7 +VITE_BASE_URL='https://fitness.hcxtec.com'
  8 +
  9 +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
  10 +VITE_UPLOAD_TYPE=server
  11 +
  12 +# 接口地址
  13 +VITE_API_URL=/admin-api
  14 +
  15 +# 是否删除debugger
  16 +VITE_DROP_DEBUGGER=false
  17 +
  18 +# 是否删除console.log
  19 +VITE_DROP_CONSOLE=false
  20 +
  21 +# 是否sourcemap
  22 +VITE_SOURCEMAP=true
  23 +
  24 +# 打包路径
  25 +VITE_BASE_PATH=/
  26 +
  27 +# 输出路径
  28 +VITE_OUT_DIR=dist
  29 +
  30 +# 商城H5会员端域名
  31 +VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
  32 +
  33 +# 验证码的开关
  34 +VITE_APP_CAPTCHA_ENABLE=false
  35 +
  36 +# GoView域名
  37 +VITE_GOVIEW_URL='http://127.0.0.1:3000'
  1 +# 本地开发环境:本地启动所有项目(前端、后端、APP)时使用,不依赖外部环境
  2 +NODE_ENV=development
  3 +
  4 +VITE_DEV=true
  5 +
  6 +# 请求路径
  7 +VITE_BASE_URL='http://192.168.1.200:48081'
  8 +
  9 +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
  10 +VITE_UPLOAD_TYPE=server
  11 +
  12 +# 接口地址
  13 +VITE_API_URL=/admin-api
  14 +
  15 +# 是否删除debugger
  16 +VITE_DROP_DEBUGGER=false
  17 +
  18 +# 是否删除console.log
  19 +VITE_DROP_CONSOLE=false
  20 +
  21 +# 是否sourcemap
  22 +VITE_SOURCEMAP=false
  23 +
  24 +# 打包路径
  25 +VITE_BASE_PATH=/
  26 +
  27 +# 商城H5会员端域名
  28 +VITE_MALL_H5_DOMAIN='http://localhost:3000'
  29 +
  30 +# 验证码的开关
  31 +VITE_APP_CAPTCHA_ENABLE=false
  32 +
  33 +# GoView域名
  34 +VITE_GOVIEW_URL='http://127.0.0.1:3000'
  1 +# 生产环境:只在打包时使用
  2 +NODE_ENV=production
  3 +
  4 +VITE_DEV=false
  5 +
  6 +# 请求路径
  7 +VITE_BASE_URL='http://localhost:48080'
  8 +
  9 +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
  10 +VITE_UPLOAD_TYPE=server
  11 +
  12 +# 接口地址
  13 +VITE_API_URL=/admin-api
  14 +
  15 +# 是否删除debugger
  16 +VITE_DROP_DEBUGGER=true
  17 +
  18 +# 是否删除console.log
  19 +VITE_DROP_CONSOLE=true
  20 +
  21 +# 是否sourcemap
  22 +VITE_SOURCEMAP=false
  23 +
  24 +# 打包路径
  25 +VITE_BASE_PATH=/
  26 +
  27 +# 输出路径
  28 +VITE_OUT_DIR=dist-prod
  29 +
  30 +# 商城H5会员端域名
  31 +VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
  32 +
  33 +# GoView域名
  34 +VITE_GOVIEW_URL='http://127.0.0.1:3000'
  1 +# 预发布环境:只在打包时使用
  2 +NODE_ENV=production
  3 +
  4 +VITE_DEV=false
  5 +
  6 +# 请求路径
  7 +VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
  8 +
  9 +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
  10 +VITE_UPLOAD_TYPE=server
  11 +
  12 +# 接口地址
  13 +VITE_API_URL=/admin-api
  14 +
  15 +# 是否删除debugger
  16 +VITE_DROP_DEBUGGER=true
  17 +
  18 +# 是否删除console.log
  19 +VITE_DROP_CONSOLE=true
  20 +
  21 +# 是否sourcemap
  22 +VITE_SOURCEMAP=false
  23 +
  24 +# 打包路径
  25 +VITE_BASE_PATH='http://static-vue3.yudao.iocoder.cn/'
  26 +
  27 +# 输出路径
  28 +VITE_OUT_DIR=dist-stage
  29 +
  30 +# 商城H5会员端域名
  31 +VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
  32 +
  33 +# GoView域名
  34 +VITE_GOVIEW_URL='http://127.0.0.1:3000'
  1 +# 测试环境:只在打包时使用
  2 +NODE_ENV=production
  3 +
  4 +VITE_DEV=false
  5 +
  6 +# 请求路径
  7 +VITE_BASE_URL='https://fitness.hcxtec.com'
  8 +
  9 +# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
  10 +VITE_UPLOAD_TYPE=server
  11 +
  12 +# 接口地址
  13 +VITE_API_URL=/admin-api
  14 +
  15 +# 是否删除debugger
  16 +VITE_DROP_DEBUGGER=true
  17 +
  18 +# 是否删除console.log
  19 +VITE_DROP_CONSOLE=true
  20 +
  21 +# 是否sourcemap
  22 +VITE_SOURCEMAP=false
  23 +
  24 +# 打包路径
  25 +VITE_BASE_PATH=/
  26 +
  27 +# 输出路径
  28 +VITE_OUT_DIR=dist
  29 +
  30 +# 商城H5会员端域名
  31 +VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
  32 +
  33 +# GoView域名
  34 +VITE_GOVIEW_URL='http://127.0.0.1:3000'
  1 +/build/
  2 +/config/
  3 +/dist/
  4 +/*.js
  5 +/test/unit/coverage/
  6 +/node_modules/*
  7 +/dist*
  8 +/src/main.ts
  1 +{
  2 + "globals": {
  3 + "EffectScope": true,
  4 + "ElMessage": true,
  5 + "ElMessageBox": true,
  6 + "ElTag": true,
  7 + "asyncComputed": true,
  8 + "autoResetRef": true,
  9 + "computed": true,
  10 + "computedAsync": true,
  11 + "computedEager": true,
  12 + "computedInject": true,
  13 + "computedWithControl": true,
  14 + "controlledComputed": true,
  15 + "controlledRef": true,
  16 + "createApp": true,
  17 + "createEventHook": true,
  18 + "createGlobalState": true,
  19 + "createInjectionState": true,
  20 + "createReactiveFn": true,
  21 + "createSharedComposable": true,
  22 + "createUnrefFn": true,
  23 + "customRef": true,
  24 + "debouncedRef": true,
  25 + "debouncedWatch": true,
  26 + "defineAsyncComponent": true,
  27 + "defineComponent": true,
  28 + "eagerComputed": true,
  29 + "effectScope": true,
  30 + "extendRef": true,
  31 + "getCurrentInstance": true,
  32 + "getCurrentScope": true,
  33 + "h": true,
  34 + "ignorableWatch": true,
  35 + "inject": true,
  36 + "isDefined": true,
  37 + "isProxy": true,
  38 + "isReactive": true,
  39 + "isReadonly": true,
  40 + "isRef": true,
  41 + "makeDestructurable": true,
  42 + "markRaw": true,
  43 + "nextTick": true,
  44 + "onActivated": true,
  45 + "onBeforeMount": true,
  46 + "onBeforeUnmount": true,
  47 + "onBeforeUpdate": true,
  48 + "onClickOutside": true,
  49 + "onDeactivated": true,
  50 + "onErrorCaptured": true,
  51 + "onKeyStroke": true,
  52 + "onLongPress": true,
  53 + "onMounted": true,
  54 + "onRenderTracked": true,
  55 + "onRenderTriggered": true,
  56 + "onScopeDispose": true,
  57 + "onServerPrefetch": true,
  58 + "onStartTyping": true,
  59 + "onUnmounted": true,
  60 + "onUpdated": true,
  61 + "pausableWatch": true,
  62 + "provide": true,
  63 + "reactify": true,
  64 + "reactifyObject": true,
  65 + "reactive": true,
  66 + "reactiveComputed": true,
  67 + "reactiveOmit": true,
  68 + "reactivePick": true,
  69 + "readonly": true,
  70 + "ref": true,
  71 + "refAutoReset": true,
  72 + "refDebounced": true,
  73 + "refDefault": true,
  74 + "refThrottled": true,
  75 + "refWithControl": true,
  76 + "resolveComponent": true,
  77 + "resolveRef": true,
  78 + "resolveUnref": true,
  79 + "shallowReactive": true,
  80 + "shallowReadonly": true,
  81 + "shallowRef": true,
  82 + "syncRef": true,
  83 + "syncRefs": true,
  84 + "templateRef": true,
  85 + "throttledRef": true,
  86 + "throttledWatch": true,
  87 + "toRaw": true,
  88 + "toReactive": true,
  89 + "toRef": true,
  90 + "toRefs": true,
  91 + "triggerRef": true,
  92 + "tryOnBeforeMount": true,
  93 + "tryOnBeforeUnmount": true,
  94 + "tryOnMounted": true,
  95 + "tryOnScopeDispose": true,
  96 + "tryOnUnmounted": true,
  97 + "unref": true,
  98 + "unrefElement": true,
  99 + "until": true,
  100 + "useActiveElement": true,
  101 + "useArrayEvery": true,
  102 + "useArrayFilter": true,
  103 + "useArrayFind": true,
  104 + "useArrayFindIndex": true,
  105 + "useArrayJoin": true,
  106 + "useArrayMap": true,
  107 + "useArrayReduce": true,
  108 + "useArraySome": true,
  109 + "useAsyncQueue": true,
  110 + "useAsyncState": true,
  111 + "useAttrs": true,
  112 + "useBase64": true,
  113 + "useBattery": true,
  114 + "useBluetooth": true,
  115 + "useBreakpoints": true,
  116 + "useBroadcastChannel": true,
  117 + "useBrowserLocation": true,
  118 + "useCached": true,
  119 + "useClipboard": true,
  120 + "useColorMode": true,
  121 + "useConfirmDialog": true,
  122 + "useCounter": true,
  123 + "useCssModule": true,
  124 + "useCssVar": true,
  125 + "useCssVars": true,
  126 + "useCurrentElement": true,
  127 + "useCycleList": true,
  128 + "useDark": true,
  129 + "useDateFormat": true,
  130 + "useDebounce": true,
  131 + "useDebounceFn": true,
  132 + "useDebouncedRefHistory": true,
  133 + "useDeviceMotion": true,
  134 + "useDeviceOrientation": true,
  135 + "useDevicePixelRatio": true,
  136 + "useDevicesList": true,
  137 + "useDisplayMedia": true,
  138 + "useDocumentVisibility": true,
  139 + "useDraggable": true,
  140 + "useDropZone": true,
  141 + "useElementBounding": true,
  142 + "useElementByPoint": true,
  143 + "useElementHover": true,
  144 + "useElementSize": true,
  145 + "useElementVisibility": true,
  146 + "useEventBus": true,
  147 + "useEventListener": true,
  148 + "useEventSource": true,
  149 + "useEyeDropper": true,
  150 + "useFavicon": true,
  151 + "useFetch": true,
  152 + "useFileDialog": true,
  153 + "useFileSystemAccess": true,
  154 + "useFocus": true,
  155 + "useFocusWithin": true,
  156 + "useFps": true,
  157 + "useFullscreen": true,
  158 + "useGamepad": true,
  159 + "useGeolocation": true,
  160 + "useIdle": true,
  161 + "useImage": true,
  162 + "useInfiniteScroll": true,
  163 + "useIntersectionObserver": true,
  164 + "useInterval": true,
  165 + "useIntervalFn": true,
  166 + "useKeyModifier": true,
  167 + "useLastChanged": true,
  168 + "useLocalStorage": true,
  169 + "useMagicKeys": true,
  170 + "useManualRefHistory": true,
  171 + "useMediaControls": true,
  172 + "useMediaQuery": true,
  173 + "useMemoize": true,
  174 + "useMemory": true,
  175 + "useMounted": true,
  176 + "useMouse": true,
  177 + "useMouseInElement": true,
  178 + "useMousePressed": true,
  179 + "useMutationObserver": true,
  180 + "useNavigatorLanguage": true,
  181 + "useNetwork": true,
  182 + "useNow": true,
  183 + "useObjectUrl": true,
  184 + "useOffsetPagination": true,
  185 + "useOnline": true,
  186 + "usePageLeave": true,
  187 + "useParallax": true,
  188 + "usePermission": true,
  189 + "usePointer": true,
  190 + "usePointerSwipe": true,
  191 + "usePreferredColorScheme": true,
  192 + "usePreferredDark": true,
  193 + "usePreferredLanguages": true,
  194 + "useRafFn": true,
  195 + "useRefHistory": true,
  196 + "useResizeObserver": true,
  197 + "useRoute": true,
  198 + "useRouter": true,
  199 + "useScreenOrientation": true,
  200 + "useScreenSafeArea": true,
  201 + "useScriptTag": true,
  202 + "useScroll": true,
  203 + "useScrollLock": true,
  204 + "useSessionStorage": true,
  205 + "useShare": true,
  206 + "useSlots": true,
  207 + "useSpeechRecognition": true,
  208 + "useSpeechSynthesis": true,
  209 + "useStepper": true,
  210 + "useStorage": true,
  211 + "useStorageAsync": true,
  212 + "useStyleTag": true,
  213 + "useSupported": true,
  214 + "useSwipe": true,
  215 + "useTemplateRefsList": true,
  216 + "useTextDirection": true,
  217 + "useTextSelection": true,
  218 + "useTextareaAutosize": true,
  219 + "useThrottle": true,
  220 + "useThrottleFn": true,
  221 + "useThrottledRefHistory": true,
  222 + "useTimeAgo": true,
  223 + "useTimeout": true,
  224 + "useTimeoutFn": true,
  225 + "useTimeoutPoll": true,
  226 + "useTimestamp": true,
  227 + "useTitle": true,
  228 + "useToggle": true,
  229 + "useTransition": true,
  230 + "useUrlSearchParams": true,
  231 + "useUserMedia": true,
  232 + "useVModel": true,
  233 + "useVModels": true,
  234 + "useVibrate": true,
  235 + "useVirtualList": true,
  236 + "useWakeLock": true,
  237 + "useWebNotification": true,
  238 + "useWebSocket": true,
  239 + "useWebWorker": true,
  240 + "useWebWorkerFn": true,
  241 + "useWindowFocus": true,
  242 + "useWindowScroll": true,
  243 + "useWindowSize": true,
  244 + "watch": true,
  245 + "watchArray": true,
  246 + "watchAtMost": true,
  247 + "watchDebounced": true,
  248 + "watchEffect": true,
  249 + "watchIgnorable": true,
  250 + "watchOnce": true,
  251 + "watchPausable": true,
  252 + "watchPostEffect": true,
  253 + "watchSyncEffect": true,
  254 + "watchThrottled": true,
  255 + "watchTriggerable": true,
  256 + "watchWithFilter": true,
  257 + "whenever": true
  258 + }
  259 +}
  1 +// @ts-check
  2 +const { defineConfig } = require('eslint-define-config')
  3 +module.exports = defineConfig({
  4 + root: true,
  5 + env: {
  6 + browser: true,
  7 + node: true,
  8 + es6: true
  9 + },
  10 + parser: 'vue-eslint-parser',
  11 + parserOptions: {
  12 + parser: '@typescript-eslint/parser',
  13 + ecmaVersion: 2020,
  14 + sourceType: 'module',
  15 + jsxPragma: 'React',
  16 + ecmaFeatures: {
  17 + jsx: true
  18 + }
  19 + },
  20 + extends: [
  21 + 'plugin:vue/vue3-recommended',
  22 + 'plugin:@typescript-eslint/recommended',
  23 + 'prettier',
  24 + 'plugin:prettier/recommended',
  25 + '@unocss'
  26 + ],
  27 + rules: {
  28 + 'vue/no-setup-props-destructure': 'off',
  29 + 'vue/script-setup-uses-vars': 'error',
  30 + 'vue/no-reserved-component-names': 'off',
  31 + '@typescript-eslint/ban-ts-ignore': 'off',
  32 + '@typescript-eslint/explicit-function-return-type': 'off',
  33 + '@typescript-eslint/no-explicit-any': 'off',
  34 + '@typescript-eslint/no-var-requires': 'off',
  35 + '@typescript-eslint/no-empty-function': 'off',
  36 + 'vue/custom-event-name-casing': 'off',
  37 + 'no-use-before-define': 'off',
  38 + '@typescript-eslint/no-use-before-define': 'off',
  39 + '@typescript-eslint/ban-ts-comment': 'off',
  40 + '@typescript-eslint/ban-types': 'off',
  41 + '@typescript-eslint/no-non-null-assertion': 'off',
  42 + '@typescript-eslint/explicit-module-boundary-types': 'off',
  43 + '@typescript-eslint/no-unused-vars': 'off',
  44 + 'no-unused-vars': 'off',
  45 + 'space-before-function-paren': 'off',
  46 +
  47 + 'vue/attributes-order': 'off',
  48 + 'vue/one-component-per-file': 'off',
  49 + 'vue/html-closing-bracket-newline': 'off',
  50 + 'vue/max-attributes-per-line': 'off',
  51 + 'vue/multiline-html-element-content-newline': 'off',
  52 + 'vue/singleline-html-element-content-newline': 'off',
  53 + 'vue/attribute-hyphenation': 'off',
  54 + 'vue/require-default-prop': 'off',
  55 + 'vue/require-explicit-emits': 'off',
  56 + 'vue/require-toggle-inside-transition': 'off',
  57 + 'vue/html-self-closing': [
  58 + 'error',
  59 + {
  60 + html: {
  61 + void: 'always',
  62 + normal: 'never',
  63 + component: 'always'
  64 + },
  65 + svg: 'always',
  66 + math: 'always'
  67 + }
  68 + ],
  69 + 'vue/multi-word-component-names': 'off',
  70 + 'vue/no-v-html': 'off',
  71 + 'prettier/prettier': 'off', // 芋艿:默认关闭 prettier 的 ESLint 校验,因为我们使用的是 IDE 的 Prettier 插件
  72 + '@unocss/order': 'off', // 芋艿:禁用 unocss 【css】顺序的提示,因为暂时不需要这么严格,警告也有点繁琐
  73 + '@unocss/order-attributify': 'off' // 芋艿:禁用 unocss 【属性】顺序的提示,因为暂时不需要这么严格,警告也有点繁琐
  74 + }
  75 +})
  1 +node_modules
  2 +.DS_Store
  3 +dist
  4 +dist-ssr
  5 +/dist*
  6 +pnpm-debug
  7 +auto-*.d.ts
  8 +.idea
  9 +.history
  1 +/node_modules/**
  2 +/dist/
  3 +/dist*
  4 +/public/*
  5 +/docs/*
  6 +/vite.config.ts
  7 +/src/types/env.d.ts
  8 +/src/types/auto-components.d.ts
  9 +/src/types/auto-imports.d.ts
  10 +/docs/**/*
  11 +CHANGELOG
  1 +/dist/*
  2 +/public/*
  3 +public/*
  4 +/dist*
  5 +/src/types/env.d.ts
  6 +/docs/**/*
  1 +{
  2 + "recommendations": [
  3 + "christian-kohler.path-intellisense",
  4 + "vscode-icons-team.vscode-icons",
  5 + "davidanson.vscode-markdownlint",
  6 + "dbaeumer.vscode-eslint",
  7 + "esbenp.prettier-vscode",
  8 + "mrmlnc.vscode-less",
  9 + "lokalise.i18n-ally",
  10 + "redhat.vscode-yaml",
  11 + "csstools.postcss",
  12 + "mikestead.dotenv",
  13 + "eamodio.gitlens",
  14 + "antfu.iconify",
  15 + "antfu.unocss",
  16 + "Vue.volar"
  17 + ]
  18 +}
  1 +{
  2 + // Use IntelliSense to learn about possible attributes.
  3 + // Hover to view descriptions of existing attributes.
  4 + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  5 + "version": "0.2.0",
  6 + "configurations": [
  7 + {
  8 + "type": "msedge",
  9 + "request": "launch",
  10 + "name": "Launch Edge against localhost",
  11 + "url": "http://localhost",
  12 + "webRoot": "${workspaceFolder}/src",
  13 + "sourceMaps": true
  14 + }
  15 + ]
  16 +}
  1 +{
  2 + "typescript.tsdk": "node_modules/typescript/lib",
  3 + "npm.packageManager": "pnpm",
  4 + "editor.tabSize": 2,
  5 + "prettier.printWidth": 100, // 超过最大值换行
  6 + "editor.defaultFormatter": "esbenp.prettier-vscode",
  7 + "files.eol": "\n",
  8 + "search.exclude": {
  9 + "**/node_modules": true,
  10 + "**/*.log": true,
  11 + "**/*.log*": true,
  12 + "**/bower_components": true,
  13 + "**/dist": true,
  14 + "**/elehukouben": true,
  15 + "**/.git": true,
  16 + "**/.gitignore": true,
  17 + "**/.svn": true,
  18 + "**/.DS_Store": true,
  19 + "**/.idea": true,
  20 + "**/.vscode": false,
  21 + "**/yarn.lock": true,
  22 + "**/tmp": true,
  23 + "out": true,
  24 + "dist": true,
  25 + "node_modules": true,
  26 + "CHANGELOG.md": true,
  27 + "examples": true,
  28 + "res": true,
  29 + "screenshots": true,
  30 + "yarn-error.log": true,
  31 + "**/.yarn": true
  32 + },
  33 + "files.exclude": {
  34 + "**/.cache": true,
  35 + "**/.editorconfig": true,
  36 + "**/.eslintcache": true,
  37 + "**/bower_components": true,
  38 + "**/.idea": true,
  39 + "**/tmp": true,
  40 + "**/.git": true,
  41 + "**/.svn": true,
  42 + "**/.hg": true,
  43 + "**/CVS": true,
  44 + "**/.DS_Store": true
  45 + },
  46 + "files.watcherExclude": {
  47 + "**/.git/objects/**": true,
  48 + "**/.git/subtree-cache/**": true,
  49 + "**/.vscode/**": true,
  50 + "**/node_modules/**": true,
  51 + "**/tmp/**": true,
  52 + "**/bower_components/**": true,
  53 + "**/dist/**": true,
  54 + "**/yarn.lock": true
  55 + },
  56 + "stylelint.enable": true,
  57 + "stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"],
  58 + "path-intellisense.mappings": {
  59 + "@/": "${workspaceRoot}/src"
  60 + },
  61 + "[javascriptreact]": {
  62 + "editor.defaultFormatter": "esbenp.prettier-vscode"
  63 + },
  64 + "[typescript]": {
  65 + "editor.defaultFormatter": "esbenp.prettier-vscode"
  66 + },
  67 + "[typescriptreact]": {
  68 + "editor.defaultFormatter": "esbenp.prettier-vscode"
  69 + },
  70 + "[html]": {
  71 + "editor.defaultFormatter": "esbenp.prettier-vscode"
  72 + },
  73 + "[css]": {
  74 + "editor.defaultFormatter": "esbenp.prettier-vscode"
  75 + },
  76 + "[less]": {
  77 + "editor.defaultFormatter": "esbenp.prettier-vscode"
  78 + },
  79 + "[scss]": {
  80 + "editor.defaultFormatter": "esbenp.prettier-vscode"
  81 + },
  82 + "[markdown]": {
  83 + "editor.defaultFormatter": "esbenp.prettier-vscode"
  84 + },
  85 + "editor.codeActionsOnSave": {
  86 + "source.fixAll.eslint": "explicit",
  87 + "source.fixAll.stylelint": "explicit"
  88 + },
  89 + "editor.formatOnSave": true,
  90 + "[vue]": {
  91 + "editor.defaultFormatter": "Vue.volar"
  92 + },
  93 + "i18n-ally.localesPaths": ["src/locales"],
  94 + "i18n-ally.keystyle": "nested",
  95 + "i18n-ally.sortKeys": true,
  96 + "i18n-ally.namespace": false,
  97 + "i18n-ally.enabledParsers": ["ts"],
  98 + "i18n-ally.sourceLanguage": "en",
  99 + "i18n-ally.displayLanguage": "zh-CN",
  100 + "i18n-ally.enabledFrameworks": ["vue", "react"],
  101 + "cSpell.words": [
  102 + "brotli",
  103 + "browserslist",
  104 + "codemirror",
  105 + "commitlint",
  106 + "cropperjs",
  107 + "echart",
  108 + "echarts",
  109 + "esnext",
  110 + "esno",
  111 + "iconify",
  112 + "INTLIFY",
  113 + "lintstagedrc",
  114 + "logicflow",
  115 + "nprogress",
  116 + "pinia",
  117 + "pnpm",
  118 + "qrcode",
  119 + "sider",
  120 + "sortablejs",
  121 + "stylelint",
  122 + "svgs",
  123 + "unocss",
  124 + "unplugin",
  125 + "unref",
  126 + "videojs",
  127 + "VITE",
  128 + "vitejs",
  129 + "vueuse",
  130 + "wangeditor",
  131 + "xingyu",
  132 + "yudao",
  133 + "zxcvbn"
  134 + ],
  135 + // 控制相关文件嵌套展示
  136 + "explorer.fileNesting.enabled": true,
  137 + "explorer.fileNesting.expand": false,
  138 + "explorer.fileNesting.patterns": {
  139 + "*.ts": "$(capture).test.ts, $(capture).test.tsx",
  140 + "*.tsx": "$(capture).test.ts, $(capture).test.tsx",
  141 + "*.env": "$(capture).env.*",
  142 + "package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.eslintrc-auto-import.json,.gitignore,prettier.config.js,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.js,.eslintignore"
  143 + },
  144 + "terminal.integrated.scrollback": 10000,
  145 + "nuxt.isNuxtApp": false
  146 +}
  1 +MIT License
  2 +
  3 +Copyright (c) 2021-present Archer
  4 +
  5 +Permission is hereby granted, free of charge, to any person obtaining a copy
  6 +of this software and associated documentation files (the "Software"), to deal
  7 +in the Software without restriction, including without limitation the rights
  8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9 +copies of the Software, and to permit persons to whom the Software is
  10 +furnished to do so, subject to the following conditions:
  11 +
  12 +The above copyright notice and this permission notice shall be included in all
  13 +copies or substantial portions of the Software.
  14 +
  15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21 +SOFTWARE.
  1 +**严肃声明:现在、未来都不会有商业版本,所有代码全部开源!!**
  2 +
  3 +**「我喜欢写代码,乐此不疲」**
  4 +**「我喜欢做开源,以此为乐」**
  5 +
  6 +我 🐶 在上海艰苦奋斗,早中晚在 top3 大厂认真搬砖,夜里为开源做贡献。
  7 +
  8 +如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。
  9 +
  10 +## 🐶 新手必读
  11 +
  12 +* nodejs > 16.18.0 && pnpm > 8.6.0 (强制使用pnpm)
  13 +* 演示地址【Vue3 + element-plus】:<http://dashboard-vue3.yudao.iocoder.cn>
  14 +* 演示地址【Vue3 + vben5.0(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
  15 +* 演示地址【Vue2 + element-ui】:<http://dashboard.yudao.iocoder.cn>
  16 +* 启动文档:<https://doc.iocoder.cn/quick-start/>
  17 +* 视频教程:<https://doc.iocoder.cn/video/>
  18 +
  19 +## 🐯 平台简介
  20 +
  21 +**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
  22 +
  23 +* 采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) 实现
  24 +* 改换 saas,自动引入等功能
  25 +* 使用 Element Plus 免费开源的中后台模版,具备如下特性:
  26 +
  27 +![首页](.image/demo/vue3-ep.png)
  28 +
  29 +* **最新技术栈**:使用 Vue3、Vite4 等前端前沿技术开发
  30 +* **TypeScript**: 应用程序级 JavaScript 的语言
  31 +* **主题**: 可配置的主题
  32 +* **国际化**:内置完善的国际化方案
  33 +* **权限**:内置完善的动态路由权限生成方案
  34 +* **组件**:二次封装了多个常用的组件
  35 +* **示例**:内置丰富的示例
  36 +
  37 +## 技术栈
  38 +
  39 +| 框架 | 说明 | 版本 |
  40 +|----------------------------------------------------------------------|------------------|--------|
  41 +| [Vue](https://staging-cn.vuejs.org/) | Vue 框架 | 3.3.8 |
  42 +| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 4.5.0 |
  43 +| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.4.2 |
  44 +| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 的超集 | 5.2.2 |
  45 +| [pinia](https://pinia.vuejs.org/) | Vue 存储库 替代 vuex5 | 2.1.7 |
  46 +| [vueuse](https://vueuse.org/) | 常用工具集 | 10.6.1 |
  47 +| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 9.6.5 |
  48 +| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.2.5 |
  49 +| [unocss](https://uno.antfu.me/) | 原子 css | 0.57.4 |
  50 +| [iconify](https://icon-sets.iconify.design/) | 在线图标库 | 3.1.1 |
  51 +| [wangeditor](https://www.wangeditor.com/) | 富文本编辑器 | 5.1.23 |
  52 +
  53 +## 开发工具
  54 +
  55 +推荐 VS Code 开发,配合插件如下:
  56 +
  57 +| 插件名 | 功能 |
  58 +|-------------------------------|---------------------|
  59 +| Vue - Official | Vue 与 TypeScript 支持 |
  60 +| unocss | unocss for vscode |
  61 +| Iconify IntelliSense | Iconify 预览和搜索 |
  62 +| i18n Ally | 国际化智能提示 |
  63 +| Stylelint | Css 格式化 |
  64 +| Prettier | 代码格式化 |
  65 +| ESLint | 脚本代码检查 |
  66 +| DotENV | env 文件高亮 |
  67 +
  68 +## 🔥 后端架构
  69 +
  70 +支持 Spring Boot、Spring Cloud 两种架构:
  71 +
  72 +① Spring Boot 单体架构:<https://doc.iocoder.cn>
  73 +
  74 +![架构图](/.image/common/ruoyi-vue-pro-architecture.png)
  75 +
  76 +② Spring Cloud 微服务架构:<https://cloud.iocoder.cn>
  77 +
  78 +![架构图](/.image/common/yudao-cloud-architecture.png)
  79 +
  80 +## 内置功能
  81 +
  82 +系统内置多种多种业务功能,可以用于快速你的业务系统:
  83 +
  84 +系统内置多种多种业务功能,可以用于快速你的业务系统:
  85 +
  86 +![功能分层](/.image/common/ruoyi-vue-pro-biz.png)
  87 +
  88 +* 通用模块(必选):系统功能、基础设施
  89 +* 通用模块(可选):工作流程、支付系统、数据报表、会员中心
  90 +* 业务系统(按需):ERP 系统、CRM 系统、商城系统、微信公众号、AI 大模型
  91 +
  92 +### 系统功能
  93 +
  94 +| | 功能 | 描述 |
  95 +|-----|-------|---------------------------------|
  96 +| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
  97 +| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
  98 +| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
  99 +| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
  100 +| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
  101 +| | 岗位管理 | 配置系统用户所属担任职务 |
  102 +| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
  103 +| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 |
  104 +| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
  105 +| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
  106 +| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 |
  107 +| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 |
  108 +| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
  109 +| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
  110 +| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 |
  111 +| | 通知公告 | 系统通知公告信息发布维护 |
  112 +| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
  113 +| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
  114 +| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
  115 +
  116 +![功能图](/.image/common/system-feature.png)
  117 +
  118 +### 工作流程
  119 +
  120 +![功能图](/.image/common/bpm-feature.png)
  121 +
  122 +基于 Flowable 构建,可支持信创(国产)数据库,满足中国特色流程操作:
  123 +
  124 +| BPMN 设计器 | 钉钉/飞书设计器 |
  125 +|-----------------------------|-------------------------------|
  126 +| ![](.image/工作流设计器-bpmn.jpg) | ![](.image/工作流设计器-simple.jpg) |
  127 +
  128 +> 历经头部企业生产验证,工作流引擎须标配仿钉钉/飞书 + BPMN 双设计器!!!
  129 +>
  130 +> 前者支持轻量配置简单流程,后者实现复杂场景深度编排
  131 +
  132 +| 功能列表 | 功能描述 | 是否完成 |
  133 +|------------|-------------------------------------------------------------------------------------|------|
  134 +| SIMPLE 设计器 | 仿钉钉/飞书设计器,支持拖拽搭建表单流程,10 分钟快速完成审批流程配置 | ✅ |
  135 +| BPMN 设计器 | 基于 BPMN 标准开发,适配复杂业务场景,满足多层级审批及流程自动化需求 | ✅ |
  136 +| 会签 | 同一个审批节点设置多个人(如 A、B、C 三人,三人会同时收到待办任务),需全部同意之后,审批才可到下一审批节点 | ✅ |
  137 +| 或签 | 同一个审批节点设置多个人,任意一个人处理后,就能进入下一个节点 | ✅ |
  138 +| 依次审批 | (顺序会签)同一个审批节点设置多个人(如 A、B、C 三人),三人按顺序依次收到待办,即 A 先审批,A 提交后 B 才能审批,需全部同意之后,审批才可到下一审批节点 | ✅ |
  139 +| 抄送 | 将审批结果通知给抄送人,同一个审批默认排重,不重复抄送给同一人 | ✅ |
  140 +| 驳回 | (退回)将审批重置发送给某节点,重新审批。可驳回至发起人、上一节点、任意节点 | ✅ |
  141 +| 转办 | A 转给其 B 审批,B 审批后,进入下一节点 | ✅ |
  142 +| 委派 | A 转给其 B 审批,B 审批后,转给 A,A 继续审批后进入下一节点 | ✅ |
  143 +| 加签 | 允许当前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签 | ✅ |
  144 +| 减签 | (取消加签)在当前审批人操作之前,减少审批人 | ✅ |
  145 +| 撤销 | (取消流程)流程发起人,可以对流程进行撤销处理 | ✅ |
  146 +| 终止 | 系统管理员,在任意节点终止流程实例 | ✅ |
  147 +| 表单权限 | 支持拖拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限 | ✅ |
  148 +| 超时审批 | 配置超时审批时间,超时后自动触发审批通过、不通过、驳回等操作 | ✅ |
  149 +| 自动提醒 | 配置提醒时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次 | ✅ |
  150 +| 父子流程 | 主流程设置子流程节点,子流程节点会自动触发子流程。子流程结束后,主流程才会执行(继续往下下执行),支持同步子流程、异步子流程 | ✅ |
  151 +| 条件分支 | (排它分支)用于在流程中实现决策,即根据条件选择一个分支执行 | ✅ |
  152 +| 并行分支 | 允许将流程分成多条分支,不进行条件判断,所有分支都会执行 | ✅ |
  153 +| 包容分支 | (条件分支 + 并行分支的结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支 | ✅ |
  154 +| 路由分支 | 根据条件选择一个分支执行(重定向到指定配置节点),也可以选择默认分支执行(继续往下执行) | ✅ |
  155 +| 触发节点 | 执行到该节点,触发 HTTP 请求、HTTP 回调、更新数据、删除数据等 | ✅ |
  156 +| 延迟节点 | 执行到该节点,审批等待一段时间再执行,支持固定时长、固定日期等 | ✅ |
  157 +| 拓展设置 | 流程前置/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等 | ✅ |
  158 +
  159 +### 支付系统
  160 +
  161 +| | 功能 | 描述 |
  162 +|-----|------|---------------------------|
  163 +| 🚀 | 应用信息 | 配置商户的应用信息,对接支付宝、微信等多个支付渠道 |
  164 +| 🚀 | 支付订单 | 查看用户发起的支付宝、微信等的【支付】订单 |
  165 +| 🚀 | 退款订单 | 查看用户发起的支付宝、微信等的【退款】订单 |
  166 +| 🚀 | 回调通知 | 查看支付回调业务的【支付】【退款】的通知结果 |
  167 +| 🚀 | 接入示例 | 提供接入支付系统的【支付】【退款】的功能实战 |
  168 +
  169 +### 基础设施
  170 +
  171 +| | 功能 | 描述 |
  172 +|-----|-----------|----------------------------------------------|
  173 +| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
  174 +| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
  175 +| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
  176 +| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
  177 +| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
  178 +| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
  179 +| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
  180 +| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 |
  181 +| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
  182 +| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
  183 +| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
  184 +| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
  185 +| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
  186 +| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
  187 +| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
  188 +| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
  189 +| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
  190 +| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
  191 +
  192 +![功能图](/.image/common/infra-feature.png)
  193 +
  194 +### 数据报表
  195 +
  196 +| | 功能 | 描述 |
  197 +|-----|-------|--------------------|
  198 +| 🚀 | 报表设计器 | 支持数据报表、图形报表、打印设计等 |
  199 +| 🚀 | 大屏设计器 | 拖拽生成数据大屏,内置几十种图表组件 |
  200 +
  201 +### 微信公众号
  202 +
  203 +| | 功能 | 描述 |
  204 +|----|--------|-------------------------------|
  205 +| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 |
  206 +| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 |
  207 +| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 |
  208 +| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 |
  209 +| 🚀 | 模版消息 | 配置和发送模版消息,用于向粉丝推送通知类消息 |
  210 +| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 |
  211 +| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 |
  212 +| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 |
  213 +| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 |
  214 +| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 |
  215 +| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 |
  216 +
  217 +### 商城系统
  218 +
  219 +演示地址:<https://doc.iocoder.cn/mall-preview/>
  220 +
  221 +![功能图](/.image/common/mall-feature.png)
  222 +
  223 +![功能图](/.image/common/mall-preview.png)
  224 +
  225 +### ERP 系统
  226 +
  227 +演示地址:<https://doc.iocoder.cn/erp-preview/>
  228 +
  229 +![功能图](/.image/common/erp-feature.png)
  230 +
  231 +### CRM 系统
  232 +
  233 +演示地址:<https://doc.iocoder.cn/crm-preview/>
  234 +
  235 +![功能图](/.image/common/crm-feature.png)
  236 +
  237 +### AI 大模型
  238 +
  239 +演示地址:<https://doc.iocoder.cn/ai-preview/>
  240 +
  241 +![功能图](/.image/common/ai-feature.png)
  242 +
  243 +![功能图](/.image/common/ai-preview.gif)
  244 +
  245 +## 🐷 演示图
  246 +
  247 +### 系统功能
  248 +
  249 +| 模块 | biu | biu | biu |
  250 +|----------|-----------------------------|---------------------------|--------------------------|
  251 +| 登录 & 首页 | ![登录](/.image/登录.jpg) | ![首页](/.image/首页.jpg) | ![个人中心](/.image/个人中心.jpg) |
  252 +| 用户 & 应用 | ![用户管理](/.image/用户管理.jpg) | ![令牌管理](/.image/令牌管理.jpg) | ![应用管理](/.image/应用管理.jpg) |
  253 +| 租户 & 套餐 | ![租户管理](/.image/租户管理.jpg) | ![租户套餐](/.image/租户套餐.png) | - |
  254 +| 部门 & 岗位 | ![部门管理](/.image/部门管理.jpg) | ![岗位管理](/.image/岗位管理.jpg) | - |
  255 +| 菜单 & 角色 | ![菜单管理](/.image/菜单管理.jpg) | ![角色管理](/.image/角色管理.jpg) | - |
  256 +| 审计日志 | ![操作日志](/.image/操作日志.jpg) | ![登录日志](/.image/登录日志.jpg) | - |
  257 +| 短信 | ![短信渠道](/.image/短信渠道.jpg) | ![短信模板](/.image/短信模板.jpg) | ![短信日志](/.image/短信日志.jpg) |
  258 +| 字典 & 敏感词 | ![字典类型](/.image/字典类型.jpg) | ![字典数据](/.image/字典数据.jpg) | ![敏感词](/.image/敏感词.jpg) |
  259 +| 错误码 & 通知 | ![错误码管理](/.image/错误码管理.jpg) | ![通知公告](/.image/通知公告.jpg) | - |
  260 +
  261 +### 工作流程
  262 +
  263 +| 模块 | biu | biu | biu |
  264 +|---------|---------------------------------|---------------------------------|---------------------------------|
  265 +| 流程模型 | ![流程模型-列表](/.image/流程模型-列表.jpg) | ![流程模型-设计](/.image/流程模型-设计.jpg) | ![流程模型-定义](/.image/流程模型-定义.jpg) |
  266 +| 表单 & 分组 | ![流程表单](/.image/流程表单.jpg) | ![用户分组](/.image/用户分组.jpg) | - |
  267 +| 我的流程 | ![我的流程-列表](/.image/我的流程-列表.jpg) | ![我的流程-发起](/.image/我的流程-发起.jpg) | ![我的流程-详情](/.image/我的流程-详情.jpg) |
  268 +| 待办 & 已办 | ![任务列表-审批](/.image/任务列表-审批.jpg) | ![任务列表-待办](/.image/任务列表-待办.jpg) | ![任务列表-已办](/.image/任务列表-已办.jpg) |
  269 +| OA 请假 | ![OA请假-列表](/.image/OA请假-列表.jpg) | ![OA请假-发起](/.image/OA请假-发起.jpg) | ![OA请假-详情](/.image/OA请假-详情.jpg) |
  270 +
  271 +### 基础设施
  272 +
  273 +| 模块 | biu | biu | biu |
  274 +|---------------|-------------------------------|-----------------------------|---------------------------|
  275 +| 代码生成 | ![代码生成](/.image/代码生成.jpg) | ![生成效果](/.image/生成效果.jpg) | - |
  276 +| 文档 | ![系统接口](/.image/系统接口.jpg) | ![数据库文档](/.image/数据库文档.jpg) | - |
  277 +| 文件 & 配置 | ![文件配置](/.image/文件配置.jpg) | ![文件管理](/.image/文件管理2.jpg) | ![配置管理](/.image/配置管理.jpg) |
  278 +| 定时任务 | ![定时任务](/.image/定时任务.jpg) | ![任务日志](/.image/任务日志.jpg) | - |
  279 +| API 日志 | ![访问日志](/.image/访问日志.jpg) | ![错误日志](/.image/错误日志.jpg) | - |
  280 +| MySQL & Redis | ![MySQL](/.image/MySQL.jpg) | ![Redis](/.image/Redis.jpg) | - |
  281 +| 监控平台 | ![Java监控](/.image/Java监控.jpg) | ![链路追踪](/.image/链路追踪.jpg) | ![日志中心](/.image/日志中心.jpg) |
  282 +
  283 +### 支付系统
  284 +
  285 +| 模块 | biu | biu | biu |
  286 +|---------|---------------------------|---------------------------------|---------------------------------|
  287 +| 商家 & 应用 | ![商户信息](/.image/商户信息.jpg) | ![应用信息-列表](/.image/应用信息-列表.jpg) | ![应用信息-编辑](/.image/应用信息-编辑.jpg) |
  288 +| 支付 & 退款 | ![支付订单](/.image/支付订单.jpg) | ![退款订单](/.image/退款订单.jpg) | --- |
  289 +
  290 +### 数据报表
  291 +
  292 +| 模块 | biu | biu | biu |
  293 +|-------|---------------------------------|---------------------------------|---------------------------------------|
  294 +| 报表设计器 | ![数据报表](/.image/报表设计器-数据报表.jpg) | ![图形报表](/.image/报表设计器-图形报表.jpg) | ![报表设计器-打印设计](/.image/报表设计器-打印设计.jpg) |
  295 +| 大屏设计器 | ![大屏列表](/.image/大屏设计器-列表.jpg) | ![大屏预览](/.image/大屏设计器-预览.jpg) | ![大屏编辑](/.image/大屏设计器-编辑.jpg) |
  1 +import { resolve } from 'path'
  2 +import Vue from '@vitejs/plugin-vue'
  3 +import VueJsx from '@vitejs/plugin-vue-jsx'
  4 +import progress from 'vite-plugin-progress'
  5 +import EslintPlugin from 'vite-plugin-eslint'
  6 +import PurgeIcons from 'vite-plugin-purge-icons'
  7 +import { ViteEjsPlugin } from 'vite-plugin-ejs'
  8 +// @ts-ignore
  9 +import ElementPlus from 'unplugin-element-plus/vite'
  10 +import AutoImport from 'unplugin-auto-import/vite'
  11 +import Components from 'unplugin-vue-components/vite'
  12 +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  13 +import viteCompression from 'vite-plugin-compression'
  14 +import topLevelAwait from 'vite-plugin-top-level-await'
  15 +import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
  16 +import { createSvgIconsPlugin } from 'vite-plugin-svg-icons-ng'
  17 +import UnoCSS from 'unocss/vite'
  18 +
  19 +export function createVitePlugins() {
  20 + const root = process.cwd()
  21 +
  22 + // 路径查找
  23 + function pathResolve(dir: string) {
  24 + return resolve(root, '.', dir)
  25 + }
  26 +
  27 + return [
  28 + Vue(),
  29 + VueJsx(),
  30 + UnoCSS(),
  31 + progress(),
  32 + PurgeIcons(),
  33 + ElementPlus({}),
  34 + AutoImport({
  35 + include: [
  36 + /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
  37 + /\.vue$/,
  38 + /\.vue\?vue/, // .vue
  39 + /\.md$/ // .md
  40 + ],
  41 + imports: [
  42 + 'vue',
  43 + 'vue-router',
  44 + // 可额外添加需要 autoImport 的组件
  45 + {
  46 + '@/hooks/web/useI18n': ['useI18n'],
  47 + '@/hooks/web/useMessage': ['useMessage'],
  48 + '@/hooks/web/useTable': ['useTable'],
  49 + '@/hooks/web/useCrudSchemas': ['useCrudSchemas'],
  50 + '@/utils/formRules': ['required'],
  51 + '@/utils/dict': ['DICT_TYPE']
  52 + }
  53 + ],
  54 + dts: 'src/types/auto-imports.d.ts',
  55 + resolvers: [ElementPlusResolver()],
  56 + eslintrc: {
  57 + enabled: false, // Default `false`
  58 + filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
  59 + globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
  60 + }
  61 + }),
  62 + Components({
  63 + // 生成自定义 `auto-components.d.ts` 全局声明
  64 + dts: 'src/types/auto-components.d.ts',
  65 + // 自定义组件的解析器
  66 + resolvers: [ElementPlusResolver()],
  67 + globs: ["src/components/**/**.{vue, md}", '!src/components/DiyEditor/components/mobile/**']
  68 + }),
  69 + EslintPlugin({
  70 + cache: false,
  71 + include: ['src/**/*.vue', 'src/**/*.ts', 'src/**/*.tsx'] // 检查的文件
  72 + }),
  73 + VueI18nPlugin({
  74 + runtimeOnly: true,
  75 + compositionOnly: true,
  76 + include: [resolve(__dirname, 'src/locales/**')]
  77 + }),
  78 + createSvgIconsPlugin({
  79 + iconDirs: [pathResolve('src/assets/svgs')],
  80 + symbolId: 'icon-[dir]-[name]',
  81 + }),
  82 + viteCompression({
  83 + verbose: true, // 是否在控制台输出压缩结果
  84 + disable: false, // 是否禁用
  85 + threshold: 10240, // 体积大于 threshold 才会被压缩,单位 b
  86 + algorithm: 'gzip', // 压缩算法,可选 [ 'gzip' , 'brotliCompress' ,'deflate' , 'deflateRaw']
  87 + ext: '.gz', // 生成的压缩包后缀
  88 + deleteOriginFile: false //压缩后是否删除源文件
  89 + }),
  90 + ViteEjsPlugin(),
  91 + topLevelAwait({
  92 + // https://juejin.cn/post/7152191742513512485
  93 + // The export name of top-level await promise for each chunk module
  94 + promiseExportName: '__tla',
  95 + // The function to generate import names of top-level await promise in each chunk module
  96 + promiseImportName: (i) => `__tla_${i}`
  97 + })
  98 + ]
  99 +}
  1 +const include = [
  2 + 'qs',
  3 + 'url',
  4 + 'vue',
  5 + 'sass',
  6 + 'mitt',
  7 + 'axios',
  8 + 'pinia',
  9 + 'dayjs',
  10 + 'qrcode',
  11 + 'unocss',
  12 + 'vue-router',
  13 + 'vue-types',
  14 + 'vue-i18n',
  15 + 'crypto-js',
  16 + 'cropperjs',
  17 + 'lodash-es',
  18 + 'nprogress',
  19 + 'web-storage-cache',
  20 + '@iconify/iconify',
  21 + '@vueuse/core',
  22 + '@zxcvbn-ts/core',
  23 + 'echarts/core',
  24 + 'echarts/charts',
  25 + 'echarts/components',
  26 + 'echarts/renderers',
  27 + 'echarts-wordcloud',
  28 + '@wangeditor-next/editor',
  29 + '@wangeditor-next/editor-for-vue',
  30 + '@microsoft/fetch-event-source',
  31 + 'markdown-it',
  32 + 'markmap-view',
  33 + 'markmap-lib',
  34 + 'markmap-toolbar',
  35 + 'highlight.js',
  36 + 'element-plus',
  37 + 'element-plus/es',
  38 + 'element-plus/es/locale/lang/zh-cn',
  39 + 'element-plus/es/locale/lang/en',
  40 + 'element-plus/es/components/avatar/style/css',
  41 + 'element-plus/es/components/space/style/css',
  42 + 'element-plus/es/components/backtop/style/css',
  43 + 'element-plus/es/components/form/style/css',
  44 + 'element-plus/es/components/radio-group/style/css',
  45 + 'element-plus/es/components/radio/style/css',
  46 + 'element-plus/es/components/checkbox/style/css',
  47 + 'element-plus/es/components/checkbox-group/style/css',
  48 + 'element-plus/es/components/switch/style/css',
  49 + 'element-plus/es/components/time-picker/style/css',
  50 + 'element-plus/es/components/date-picker/style/css',
  51 + 'element-plus/es/components/descriptions/style/css',
  52 + 'element-plus/es/components/descriptions-item/style/css',
  53 + 'element-plus/es/components/link/style/css',
  54 + 'element-plus/es/components/tooltip/style/css',
  55 + 'element-plus/es/components/drawer/style/css',
  56 + 'element-plus/es/components/dialog/style/css',
  57 + 'element-plus/es/components/checkbox-button/style/css',
  58 + 'element-plus/es/components/option-group/style/css',
  59 + 'element-plus/es/components/radio-button/style/css',
  60 + 'element-plus/es/components/cascader/style/css',
  61 + 'element-plus/es/components/color-picker/style/css',
  62 + 'element-plus/es/components/input-number/style/css',
  63 + 'element-plus/es/components/rate/style/css',
  64 + 'element-plus/es/components/select-v2/style/css',
  65 + 'element-plus/es/components/tree-select/style/css',
  66 + 'element-plus/es/components/slider/style/css',
  67 + 'element-plus/es/components/time-select/style/css',
  68 + 'element-plus/es/components/autocomplete/style/css',
  69 + 'element-plus/es/components/image-viewer/style/css',
  70 + 'element-plus/es/components/upload/style/css',
  71 + 'element-plus/es/components/col/style/css',
  72 + 'element-plus/es/components/form-item/style/css',
  73 + 'element-plus/es/components/alert/style/css',
  74 + 'element-plus/es/components/breadcrumb/style/css',
  75 + 'element-plus/es/components/select/style/css',
  76 + 'element-plus/es/components/input/style/css',
  77 + 'element-plus/es/components/breadcrumb-item/style/css',
  78 + 'element-plus/es/components/tag/style/css',
  79 + 'element-plus/es/components/pagination/style/css',
  80 + 'element-plus/es/components/table/style/css',
  81 + 'element-plus/es/components/table-v2/style/css',
  82 + 'element-plus/es/components/table-column/style/css',
  83 + 'element-plus/es/components/card/style/css',
  84 + 'element-plus/es/components/row/style/css',
  85 + 'element-plus/es/components/button/style/css',
  86 + 'element-plus/es/components/menu/style/css',
  87 + 'element-plus/es/components/sub-menu/style/css',
  88 + 'element-plus/es/components/menu-item/style/css',
  89 + 'element-plus/es/components/option/style/css',
  90 + 'element-plus/es/components/dropdown/style/css',
  91 + 'element-plus/es/components/dropdown-menu/style/css',
  92 + 'element-plus/es/components/dropdown-item/style/css',
  93 + 'element-plus/es/components/skeleton/style/css',
  94 + 'element-plus/es/components/skeleton/style/css',
  95 + 'element-plus/es/components/backtop/style/css',
  96 + 'element-plus/es/components/menu/style/css',
  97 + 'element-plus/es/components/sub-menu/style/css',
  98 + 'element-plus/es/components/menu-item/style/css',
  99 + 'element-plus/es/components/dropdown/style/css',
  100 + 'element-plus/es/components/tree/style/css',
  101 + 'element-plus/es/components/dropdown-menu/style/css',
  102 + 'element-plus/es/components/dropdown-item/style/css',
  103 + 'element-plus/es/components/badge/style/css',
  104 + 'element-plus/es/components/breadcrumb/style/css',
  105 + 'element-plus/es/components/breadcrumb-item/style/css',
  106 + 'element-plus/es/components/image/style/css',
  107 + 'element-plus/es/components/collapse-transition/style/css',
  108 + 'element-plus/es/components/timeline/style/css',
  109 + 'element-plus/es/components/timeline-item/style/css',
  110 + 'element-plus/es/components/collapse/style/css',
  111 + 'element-plus/es/components/collapse-item/style/css',
  112 + 'element-plus/es/components/button-group/style/css',
  113 + 'element-plus/es/components/text/style/css',
  114 + 'element-plus/es/components/segmented/style/css',
  115 + '@element-plus/icons-vue',
  116 + 'element-plus/es/components/footer/style/css',
  117 + 'element-plus/es/components/empty/style/css',
  118 + 'element-plus/es/components/mention/style/css',
  119 + 'element-plus/es/components/progress/style/css'
  120 +]
  121 +
  122 +const exclude = ['@iconify/json']
  123 +
  124 +export { include, exclude }
  1 +<!DOCTYPE html>
  2 +<html lang="en">
  3 + <head>
  4 + <meta charset="UTF-8" />
  5 + <link rel="icon" href="/favicon.ico" />
  6 + <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  7 + <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  8 + <meta
  9 + name="keywords"
  10 + content="芋道管理系统 基于 vue3 + CompositionAPI + typescript + vite3 + element plus 的后台开源免费管理系统!"
  11 + />
  12 + <meta
  13 + name="description"
  14 + content="芋道管理系统 基于 vue3 + CompositionAPI + typescript + vite3 + element plus 的后台开源免费管理系统!"
  15 + />
  16 + <title>%VITE_APP_TITLE%</title>
  17 + </head>
  18 + <body>
  19 + <div id="app">
  20 + <style>
  21 + .app-loading {
  22 + display: flex;
  23 + width: 100%;
  24 + height: 100%;
  25 + justify-content: center;
  26 + align-items: center;
  27 + flex-direction: column;
  28 + background: #f0f2f5;
  29 + }
  30 +
  31 + .app-loading .app-loading-wrap {
  32 + position: absolute;
  33 + top: 50%;
  34 + left: 50%;
  35 + display: flex;
  36 + -webkit-transform: translate3d(-50%, -50%, 0);
  37 + transform: translate3d(-50%, -50%, 0);
  38 + justify-content: center;
  39 + align-items: center;
  40 + flex-direction: column;
  41 + }
  42 +
  43 + .app-loading .app-loading-title {
  44 + margin-bottom: 30px;
  45 + font-size: 20px;
  46 + font-weight: bold;
  47 + text-align: center;
  48 + }
  49 +
  50 + .app-loading .app-loading-logo {
  51 + width: 100px;
  52 + margin: 0 auto 15px auto;
  53 + }
  54 +
  55 + .app-loading .app-loading-item {
  56 + position: relative;
  57 + display: inline-block;
  58 + width: 60px;
  59 + height: 60px;
  60 + vertical-align: middle;
  61 + border-radius: 50%;
  62 + }
  63 +
  64 + .app-loading .app-loading-outter {
  65 + position: absolute;
  66 + width: 100%;
  67 + height: 100%;
  68 + border: 4px solid #2d8cf0;
  69 + border-bottom: 0;
  70 + border-left-color: transparent;
  71 + border-radius: 50%;
  72 + animation: loader-outter 1s cubic-bezier(0.42, 0.61, 0.58, 0.41) infinite;
  73 + }
  74 +
  75 + .app-loading .app-loading-inner {
  76 + position: absolute;
  77 + top: calc(50% - 20px);
  78 + left: calc(50% - 20px);
  79 + width: 40px;
  80 + height: 40px;
  81 + border: 4px solid #87bdff;
  82 + border-right: 0;
  83 + border-top-color: transparent;
  84 + border-radius: 50%;
  85 + animation: loader-inner 1s cubic-bezier(0.42, 0.61, 0.58, 0.41) infinite;
  86 + }
  87 +
  88 + @-webkit-keyframes loader-outter {
  89 + 0% {
  90 + -webkit-transform: rotate(0deg);
  91 + transform: rotate(0deg);
  92 + }
  93 +
  94 + 100% {
  95 + -webkit-transform: rotate(360deg);
  96 + transform: rotate(360deg);
  97 + }
  98 + }
  99 +
  100 + @keyframes loader-outter {
  101 + 0% {
  102 + -webkit-transform: rotate(0deg);
  103 + transform: rotate(0deg);
  104 + }
  105 +
  106 + 100% {
  107 + -webkit-transform: rotate(360deg);
  108 + transform: rotate(360deg);
  109 + }
  110 + }
  111 +
  112 + @-webkit-keyframes loader-inner {
  113 + 0% {
  114 + -webkit-transform: rotate(0deg);
  115 + transform: rotate(0deg);
  116 + }
  117 +
  118 + 100% {
  119 + -webkit-transform: rotate(-360deg);
  120 + transform: rotate(-360deg);
  121 + }
  122 + }
  123 +
  124 + @keyframes loader-inner {
  125 + 0% {
  126 + -webkit-transform: rotate(0deg);
  127 + transform: rotate(0deg);
  128 + }
  129 +
  130 + 100% {
  131 + -webkit-transform: rotate(-360deg);
  132 + transform: rotate(-360deg);
  133 + }
  134 + }
  135 + </style>
  136 + <div class="app-loading">
  137 + <div class="app-loading-wrap">
  138 + <div class="app-loading-title">
  139 + <img src="/logo.gif" class="app-loading-logo" alt="Logo" />
  140 + <div class="app-loading-title">%VITE_APP_TITLE%</div>
  141 + </div>
  142 + <div class="app-loading-item">
  143 + <div class="app-loading-outter"></div>
  144 + <div class="app-loading-inner"></div>
  145 + </div>
  146 + </div>
  147 + </div>
  148 + </div>
  149 + <script type="module" src="/src/main.ts"></script>
  150 + </body>
  151 +</html>
This diff could not be displayed because it is too large.
  1 +{
  2 + "name": "yudao-ui-admin-vue3",
  3 + "version": "2025.11-snapshot",
  4 + "description": "基于vue3、vite4、element-plus、typesScript",
  5 + "author": "xingyu",
  6 + "private": false,
  7 + "scripts": {
  8 + "i": "pnpm install",
  9 + "dev": "vite --mode env.local",
  10 + "dev-server": "vite --mode dev",
  11 + "ts:check": "vue-tsc --noEmit",
  12 + "build:local": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build",
  13 + "build:dev": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode dev",
  14 + "build:test": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode test",
  15 + "build:stage": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode stage",
  16 + "build:prod": "node --max_old_space_size=4096 ./node_modules/vite/bin/vite.js build --mode prod",
  17 + "serve:dev": "vite preview --mode dev",
  18 + "serve:prod": "vite preview --mode prod",
  19 + "preview": "pnpm build:local && vite preview",
  20 + "clean": "npx rimraf node_modules",
  21 + "clean:cache": "npx rimraf node_modules/.cache",
  22 + "lint:eslint": "eslint --fix --ext .js,.ts,.vue ./src",
  23 + "lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,scss,vue,html,md}\"",
  24 + "lint:style": "stylelint --fix \"./src/**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
  25 + "lint:lint-staged": "lint-staged -c "
  26 + },
  27 + "dependencies": {
  28 + "@element-plus/icons-vue": "^2.3.2",
  29 + "@form-create/designer": "^3.2.6",
  30 + "@form-create/element-ui": "^3.2.11",
  31 + "@iconify/iconify": "^3.1.1",
  32 + "@microsoft/fetch-event-source": "^2.0.1",
  33 + "@tinymce/tinymce-vue": "^6.3.0",
  34 + "@videojs-player/vue": "^1.0.0",
  35 + "@vueup/vue-quill": "^1.2.0",
  36 + "@vueuse/core": "^10.9.0",
  37 + "@wangeditor-next/editor": "^5.6.46",
  38 + "@wangeditor-next/editor-for-vue": "^5.1.14",
  39 + "@wangeditor-next/plugin-mention": "^1.0.16",
  40 + "@wangeditor/editor": "^5.1.23",
  41 + "@wangeditor/editor-for-vue": "^5.1.12",
  42 + "@zxcvbn-ts/core": "^3.0.4",
  43 + "animate.css": "^4.1.1",
  44 + "axios": "1.9.0",
  45 + "benz-amr-recorder": "^1.1.5",
  46 + "bpmn-js-token-simulation": "^0.36.0",
  47 + "camunda-bpmn-moddle": "^7.0.1",
  48 + "cropperjs": "^1.6.1",
  49 + "crypto-js": "^4.2.0",
  50 + "dayjs": "^1.11.10",
  51 + "diagram-js": "^12.8.0",
  52 + "driver.js": "^1.3.1",
  53 + "echarts": "^5.5.0",
  54 + "echarts-wordcloud": "^2.1.0",
  55 + "element-plus": "2.11.1",
  56 + "fast-xml-parser": "^4.3.2",
  57 + "highlight.js": "^11.9.0",
  58 + "jsencrypt": "^3.3.2",
  59 + "jsoneditor": "^10.1.3",
  60 + "lodash-es": "^4.17.21",
  61 + "markdown-it": "^14.1.0",
  62 + "markmap-common": "^0.16.0",
  63 + "markmap-lib": "^0.16.1",
  64 + "markmap-toolbar": "^0.17.0",
  65 + "markmap-view": "^0.16.0",
  66 + "min-dash": "^4.1.1",
  67 + "mitt": "^3.0.1",
  68 + "nprogress": "^0.2.0",
  69 + "pinia": "^2.1.7",
  70 + "pinia-plugin-persistedstate": "^3.2.1",
  71 + "qrcode": "^1.5.3",
  72 + "qs": "^6.12.0",
  73 + "snabbdom": "^3.6.2",
  74 + "sortablejs": "^1.15.3",
  75 + "steady-xml": "^0.1.0",
  76 + "tinymce": "^8.3.2",
  77 + "url": "^0.11.3",
  78 + "video.js": "^7.21.5",
  79 + "vue": "3.5.12",
  80 + "vue-dompurify-html": "^4.1.4",
  81 + "vue-i18n": "9.10.2",
  82 + "vue-router": "4.4.5",
  83 + "vue-types": "^5.1.1",
  84 + "vue3-print-nb": "^0.1.4",
  85 + "vue3-signature": "^0.2.4",
  86 + "vuedraggable": "^4.1.0",
  87 + "wangeditor": "^4.7.15",
  88 + "web-storage-cache": "^1.1.1",
  89 + "xml-js": "^1.6.11"
  90 + },
  91 + "devDependencies": {
  92 + "@commitlint/cli": "^19.0.1",
  93 + "@commitlint/config-conventional": "^19.0.0",
  94 + "@iconify/json": "^2.2.187",
  95 + "@intlify/unplugin-vue-i18n": "^2.0.0",
  96 + "@purge-icons/generated": "^0.9.0",
  97 + "@types/jsoneditor": "^9.9.5",
  98 + "@types/lodash-es": "^4.17.12",
  99 + "@types/node": "^20.11.21",
  100 + "@types/nprogress": "^0.2.3",
  101 + "@types/qrcode": "^1.5.5",
  102 + "@types/qs": "^6.9.12",
  103 + "@typescript-eslint/eslint-plugin": "^7.1.0",
  104 + "@typescript-eslint/parser": "^7.1.0",
  105 + "@unocss/eslint-config": "^0.57.4",
  106 + "@unocss/eslint-plugin": "66.1.0-beta.5",
  107 + "@unocss/transformer-variant-group": "^0.58.5",
  108 + "@vitejs/plugin-legacy": "^5.3.1",
  109 + "@vitejs/plugin-vue": "^5.0.4",
  110 + "@vitejs/plugin-vue-jsx": "^3.1.0",
  111 + "autoprefixer": "^10.4.17",
  112 + "bpmn-js": "^17.9.2",
  113 + "bpmn-js-properties-panel": "5.23.0",
  114 + "consola": "^3.2.3",
  115 + "eslint": "^8.57.0",
  116 + "eslint-config-prettier": "^9.1.0",
  117 + "eslint-define-config": "^2.1.0",
  118 + "eslint-plugin-prettier": "^5.1.3",
  119 + "eslint-plugin-vue": "^9.22.0",
  120 + "lint-staged": "^15.2.2",
  121 + "postcss": "^8.4.35",
  122 + "postcss-html": "^1.6.0",
  123 + "postcss-scss": "^4.0.9",
  124 + "prettier": "^3.2.5",
  125 + "prettier-eslint": "^16.3.0",
  126 + "rimraf": "^5.0.5",
  127 + "rollup": "^4.12.0",
  128 + "sass": "^1.69.5",
  129 + "stylelint": "^16.2.1",
  130 + "stylelint-config-html": "^1.1.0",
  131 + "stylelint-config-recommended": "^14.0.0",
  132 + "stylelint-config-standard": "^36.0.0",
  133 + "stylelint-order": "^6.0.4",
  134 + "terser": "^5.28.1",
  135 + "typescript": "5.3.3",
  136 + "unocss": "^0.58.5",
  137 + "unplugin-auto-import": "^0.16.7",
  138 + "unplugin-element-plus": "^0.8.0",
  139 + "unplugin-vue-components": "^0.25.2",
  140 + "vite": "5.1.4",
  141 + "vite-plugin-compression": "^0.5.1",
  142 + "vite-plugin-ejs": "^1.7.0",
  143 + "vite-plugin-eslint": "^1.8.1",
  144 + "vite-plugin-progress": "^0.0.7",
  145 + "vite-plugin-purge-icons": "^0.10.0",
  146 + "vite-plugin-svg-icons-ng": "^1.3.1",
  147 + "vite-plugin-top-level-await": "^1.4.4",
  148 + "vue-eslint-parser": "^9.3.2",
  149 + "vue-tsc": "^1.8.27"
  150 + },
  151 + "license": "MIT",
  152 + "repository": {
  153 + "type": "git",
  154 + "url": "git+https://gitee.com/yudaocode/yudao-ui-admin-vue3"
  155 + },
  156 + "bugs": {
  157 + "url": "https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues"
  158 + },
  159 + "homepage": "https://gitee.com/yudaocode/yudao-ui-admin-vue3",
  160 + "web-types": "./web-types.json",
  161 + "engines": {
  162 + "node": ">= 16.0.0",
  163 + "pnpm": ">=8.6.0"
  164 + }
  165 +}
This diff could not be displayed because it is too large.
  1 +module.exports = {
  2 + plugins: {
  3 + autoprefixer: {}
  4 + }
  5 +}
  1 +module.exports = {
  2 + printWidth: 100, // 每行代码长度(默认80)
  3 + tabWidth: 2, // 每个tab相当于多少个空格(默认2)ab进行缩进(默认false)
  4 + useTabs: false, // 是否使用tab
  5 + semi: false, // 声明结尾使用分号(默认true)
  6 + vueIndentScriptAndStyle: false,
  7 + singleQuote: true, // 使用单引号(默认false)
  8 + quoteProps: 'as-needed',
  9 + bracketSpacing: true, // 对象字面量的大括号间使用空格(默认true)
  10 + trailingComma: 'none', // 多行使用拖尾逗号(默认none)
  11 + jsxSingleQuote: false,
  12 + // 箭头函数参数括号 默认avoid 可选 avoid| always
  13 + // avoid 能省略括号的时候就省略 例如x => x
  14 + // always 总是有括号
  15 + arrowParens: 'always',
  16 + insertPragma: false,
  17 + requirePragma: false,
  18 + proseWrap: 'never',
  19 + htmlWhitespaceSensitivity: 'strict',
  20 + endOfLine: 'auto',
  21 + rangeStart: 0
  22 +}
No preview for this file type
  1 +<script lang="ts" setup>
  2 +import { isDark } from '@/utils/is'
  3 +import { useAppStore } from '@/store/modules/app'
  4 +import { useDesign } from '@/hooks/web/useDesign'
  5 +import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
  6 +import routerSearch from '@/components/RouterSearch/index.vue'
  7 +
  8 +defineOptions({ name: 'APP' })
  9 +
  10 +const { getPrefixCls } = useDesign()
  11 +const prefixCls = getPrefixCls('app')
  12 +const appStore = useAppStore()
  13 +const currentSize = computed(() => appStore.getCurrentSize)
  14 +const greyMode = computed(() => appStore.getGreyMode)
  15 +const { wsCache } = useCache()
  16 +
  17 +// 根据浏览器当前主题设置系统主题色
  18 +const setDefaultTheme = () => {
  19 + let isDarkTheme = wsCache.get(CACHE_KEY.IS_DARK)
  20 + if (isDarkTheme === null) {
  21 + isDarkTheme = isDark()
  22 + }
  23 + appStore.setIsDark(isDarkTheme)
  24 +}
  25 +setDefaultTheme()
  26 +</script>
  27 +<template>
  28 + <ConfigGlobal :size="currentSize">
  29 + <RouterView :class="greyMode ? `${prefixCls}-grey-mode` : ''" />
  30 + <routerSearch />
  31 + </ConfigGlobal>
  32 +</template>
  33 +<style lang="scss">
  34 +$prefix-cls: #{$namespace}-app;
  35 +
  36 +.size {
  37 + width: 100%;
  38 + height: 100%;
  39 +}
  40 +
  41 +html,
  42 +body {
  43 + @extend .size;
  44 +
  45 + padding: 0 !important;
  46 + margin: 0;
  47 + overflow: hidden;
  48 +
  49 + #app {
  50 + @extend .size;
  51 + }
  52 +}
  53 +
  54 +.#{$prefix-cls}-grey-mode {
  55 + filter: grayscale(100%);
  56 +}
  57 +</style>
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 聊天对话 VO
  4 +export interface ChatConversationVO {
  5 + id: number // ID 编号
  6 + userId: number // 用户编号
  7 + title: string // 对话标题
  8 + pinned: boolean // 是否置顶
  9 + roleId: number // 角色编号
  10 + modelId: number // 模型编号
  11 + model: string // 模型标志
  12 + temperature: number // 温度参数
  13 + maxTokens: number // 单条回复的最大 Token 数量
  14 + maxContexts: number // 上下文的最大 Message 数量
  15 + createTime?: Date // 创建时间
  16 + // 额外字段
  17 + systemMessage?: string // 角色设定
  18 + modelName?: string // 模型名字
  19 + roleAvatar?: string // 角色头像
  20 + modelMaxTokens?: string // 模型的单条回复的最大 Token 数量
  21 + modelMaxContexts?: string // 模型的上下文的最大 Message 数量
  22 +}
  23 +
  24 +// AI 聊天对话 API
  25 +export const ChatConversationApi = {
  26 + // 获得【我的】聊天对话
  27 + getChatConversationMy: async (id: number) => {
  28 + return await request.get({ url: `/ai/chat/conversation/get-my?id=${id}` })
  29 + },
  30 +
  31 + // 新增【我的】聊天对话
  32 + createChatConversationMy: async (data?: ChatConversationVO) => {
  33 + return await request.post({ url: `/ai/chat/conversation/create-my`, data })
  34 + },
  35 +
  36 + // 更新【我的】聊天对话
  37 + updateChatConversationMy: async (data: ChatConversationVO) => {
  38 + return await request.put({ url: `/ai/chat/conversation/update-my`, data })
  39 + },
  40 +
  41 + // 删除【我的】聊天对话
  42 + deleteChatConversationMy: async (id: string) => {
  43 + return await request.delete({ url: `/ai/chat/conversation/delete-my?id=${id}` })
  44 + },
  45 +
  46 + // 删除【我的】所有对话,置顶除外
  47 + deleteChatConversationMyByUnpinned: async () => {
  48 + return await request.delete({ url: `/ai/chat/conversation/delete-by-unpinned` })
  49 + },
  50 +
  51 + // 获得【我的】聊天对话列表
  52 + getChatConversationMyList: async () => {
  53 + return await request.get({ url: `/ai/chat/conversation/my-list` })
  54 + },
  55 +
  56 + // 获得对话分页
  57 + getChatConversationPage: async (params: any) => {
  58 + return await request.get({ url: `/ai/chat/conversation/page`, params })
  59 + },
  60 +
  61 + // 管理员删除消息
  62 + deleteChatConversationByAdmin: async (id: number) => {
  63 + return await request.delete({ url: `/ai/chat/conversation/delete-by-admin?id=${id}` })
  64 + }
  65 +}
  1 +import request from '@/config/axios'
  2 +import { fetchEventSource } from '@microsoft/fetch-event-source'
  3 +import { getAccessToken } from '@/utils/auth'
  4 +import { config } from '@/config/axios/config'
  5 +
  6 +// 聊天VO
  7 +export interface ChatMessageVO {
  8 + id: number // 编号
  9 + conversationId: number // 对话编号
  10 + type: string // 消息类型
  11 + userId: string // 用户编号
  12 + roleId: string // 角色编号
  13 + model: number // 模型标志
  14 + modelId: number // 模型编号
  15 + content: string // 聊天内容
  16 + reasoningContent?: string // 推理内容
  17 + attachmentUrls?: string[] // 附件 URL 数组
  18 + tokens: number // 消耗 Token 数量
  19 + segmentIds?: number[] // 段落编号
  20 + segments?: {
  21 + id: number // 段落编号
  22 + content: string // 段落内容
  23 + documentId: number // 文档编号
  24 + documentName: string // 文档名称
  25 + }[]
  26 + webSearchPages?: {
  27 + name: string // 名称
  28 + icon: string // 图标
  29 + title: string // 标题
  30 + url: string // URL
  31 + snippet: string // 内容的简短描述
  32 + summary: string // 内容的文本摘要
  33 + }[]
  34 + createTime: Date // 创建时间
  35 + roleAvatar: string // 角色头像
  36 + userAvatar: string // 用户头像
  37 +}
  38 +
  39 +// AI chat 聊天
  40 +export const ChatMessageApi = {
  41 + // 消息列表
  42 + getChatMessageListByConversationId: async (conversationId: number | null) => {
  43 + return await request.get({
  44 + url: `/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}`
  45 + })
  46 + },
  47 +
  48 + // 发送 Stream 消息
  49 + // 为什么不用 axios 呢?因为它不支持 SSE 调用
  50 + sendChatMessageStream: async (
  51 + conversationId: number,
  52 + content: string,
  53 + ctrl,
  54 + enableContext: boolean,
  55 + enableWebSearch: boolean,
  56 + onMessage,
  57 + onError,
  58 + onClose,
  59 + attachmentUrls?: string[]
  60 + ) => {
  61 + const token = getAccessToken()
  62 + return fetchEventSource(`${config.base_url}/ai/chat/message/send-stream`, {
  63 + method: 'post',
  64 + headers: {
  65 + 'Content-Type': 'application/json',
  66 + Authorization: `Bearer ${token}`
  67 + },
  68 + openWhenHidden: true,
  69 + body: JSON.stringify({
  70 + conversationId,
  71 + content,
  72 + useContext: enableContext,
  73 + useSearch: enableWebSearch,
  74 + attachmentUrls: attachmentUrls || []
  75 + }),
  76 + onmessage: onMessage,
  77 + onerror: onError,
  78 + onclose: onClose,
  79 + signal: ctrl.signal
  80 + })
  81 + },
  82 +
  83 + // 删除消息
  84 + deleteChatMessage: async (id: string) => {
  85 + return await request.delete({ url: `/ai/chat/message/delete?id=${id}` })
  86 + },
  87 +
  88 + // 删除指定对话的消息
  89 + deleteByConversationId: async (conversationId: number) => {
  90 + return await request.delete({
  91 + url: `/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}`
  92 + })
  93 + },
  94 +
  95 + // 获得消息分页
  96 + getChatMessagePage: async (params: any) => {
  97 + return await request.get({ url: '/ai/chat/message/page', params })
  98 + },
  99 +
  100 + // 管理员删除消息
  101 + deleteChatMessageByAdmin: async (id: number) => {
  102 + return await request.delete({ url: `/ai/chat/message/delete-by-admin?id=${id}` })
  103 + }
  104 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 绘图 VO
  4 +export interface ImageVO {
  5 + id: number // 编号
  6 + platform: string // 平台
  7 + model: string // 模型
  8 + prompt: string // 提示词
  9 + width: number // 图片宽度
  10 + height: number // 图片高度
  11 + status: number // 状态
  12 + publicStatus: boolean // 公开状态
  13 + picUrl: string // 任务地址
  14 + errorMessage: string // 错误信息
  15 + options: any // 配置 Map<string, string>
  16 + taskId: number // 任务编号
  17 + buttons: ImageMidjourneyButtonsVO[] // mj 操作按钮
  18 + createTime: Date // 创建时间
  19 + finishTime: Date // 完成时间
  20 +}
  21 +
  22 +export interface ImageDrawReqVO {
  23 + prompt: string // 提示词
  24 + modelId: number // 模型
  25 + style: string // 图像生成的风格
  26 + width: string // 图片宽度
  27 + height: string // 图片高度
  28 + options: object // 绘制参数,Map<String, String>
  29 +}
  30 +
  31 +export interface ImageMidjourneyImagineReqVO {
  32 + prompt: string // 提示词
  33 + modelId: number // 模型
  34 + base64Array: string[] // size不能为空
  35 + width: string // 图片宽度
  36 + height: string // 图片高度
  37 + version: string // 版本
  38 +}
  39 +
  40 +export interface ImageMidjourneyActionVO {
  41 + id: number // 图片编号
  42 + customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识
  43 +}
  44 +
  45 +export interface ImageMidjourneyButtonsVO {
  46 + customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识
  47 + emoji: string // 图标 emoji
  48 + label: string // Make Variations 文本
  49 + style: number // 样式: 2(Primary)、3(Green)
  50 +}
  51 +
  52 +// AI 图片 API
  53 +export const ImageApi = {
  54 + // 获取【我的】绘图分页
  55 + getImagePageMy: async (params: any) => {
  56 + return await request.get({ url: `/ai/image/my-page`, params })
  57 + },
  58 + // 获取【我的】绘图记录
  59 + getImageMy: async (id: number) => {
  60 + return await request.get({ url: `/ai/image/get-my?id=${id}` })
  61 + },
  62 + // 获取【我的】绘图记录列表
  63 + getImageListMyByIds: async (ids: number[]) => {
  64 + return await request.get({ url: `/ai/image/my-list-by-ids`, params: { ids: ids.join(',') } })
  65 + },
  66 + // 生成图片
  67 + drawImage: async (data: ImageDrawReqVO) => {
  68 + return await request.post({ url: `/ai/image/draw`, data })
  69 + },
  70 + // 删除【我的】绘画记录
  71 + deleteImageMy: async (id: number) => {
  72 + return await request.delete({ url: `/ai/image/delete-my?id=${id}` })
  73 + },
  74 +
  75 + // ================ midjourney 专属 ================
  76 +
  77 + // 【Midjourney】生成图片
  78 + midjourneyImagine: async (data: ImageMidjourneyImagineReqVO) => {
  79 + return await request.post({ url: `/ai/image/midjourney/imagine`, data })
  80 + },
  81 + // 【Midjourney】Action 操作(二次生成图片)
  82 + midjourneyAction: async (data: ImageMidjourneyActionVO) => {
  83 + return await request.post({ url: `/ai/image/midjourney/action`, data })
  84 + },
  85 +
  86 + // ================ 绘图管理 ================
  87 +
  88 + // 查询绘画分页
  89 + getImagePage: async (params: any) => {
  90 + return await request.get({ url: `/ai/image/page`, params })
  91 + },
  92 +
  93 + // 更新绘画发布状态
  94 + updateImage: async (data: any) => {
  95 + return await request.put({ url: '/ai/image/update', data })
  96 + },
  97 +
  98 + // 删除绘画
  99 + deleteImage: async (id: number) => {
  100 + return await request.delete({ url: `/ai/image/delete?id=` + id })
  101 + }
  102 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 知识库文档 VO
  4 +export interface KnowledgeDocumentVO {
  5 + id: number // 编号
  6 + knowledgeId: number // 知识库编号
  7 + name: string // 文档名称
  8 + contentLength: number // 字符数
  9 + tokens: number // token 数
  10 + segmentMaxTokens: number // 分片最大 token 数
  11 + retrievalCount: number // 召回次数
  12 + status: number // 是否启用
  13 +}
  14 +
  15 +// AI 知识库文档 API
  16 +export const KnowledgeDocumentApi = {
  17 + // 查询知识库文档分页
  18 + getKnowledgeDocumentPage: async (params: any) => {
  19 + return await request.get({ url: `/ai/knowledge/document/page`, params })
  20 + },
  21 +
  22 + // 查询知识库文档详情
  23 + getKnowledgeDocument: async (id: number) => {
  24 + return await request.get({ url: `/ai/knowledge/document/get?id=` + id })
  25 + },
  26 +
  27 + // 新增知识库文档(单个)
  28 + createKnowledgeDocument: async (data: any) => {
  29 + return await request.post({ url: `/ai/knowledge/document/create`, data })
  30 + },
  31 +
  32 + // 新增知识库文档(多个)
  33 + createKnowledgeDocumentList: async (data: any) => {
  34 + return await request.post({ url: `/ai/knowledge/document/create-list`, data })
  35 + },
  36 +
  37 + // 修改知识库文档
  38 + updateKnowledgeDocument: async (data: any) => {
  39 + return await request.put({ url: `/ai/knowledge/document/update`, data })
  40 + },
  41 +
  42 + // 修改知识库文档状态
  43 + updateKnowledgeDocumentStatus: async (data: any) => {
  44 + return await request.put({
  45 + url: `/ai/knowledge/document/update-status`,
  46 + data
  47 + })
  48 + },
  49 +
  50 + // 删除知识库文档
  51 + deleteKnowledgeDocument: async (id: number) => {
  52 + return await request.delete({ url: `/ai/knowledge/document/delete?id=` + id })
  53 + }
  54 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 知识库 VO
  4 +export interface KnowledgeVO {
  5 + id: number // 编号
  6 + name: string // 知识库名称
  7 + description: string // 知识库描述
  8 + embeddingModelId: number // 嵌入模型编号,高质量模式时维护
  9 + topK: number // topK
  10 + similarityThreshold: number // 相似度阈值
  11 +}
  12 +
  13 +// AI 知识库 API
  14 +export const KnowledgeApi = {
  15 + // 查询知识库分页
  16 + getKnowledgePage: async (params: any) => {
  17 + return await request.get({ url: `/ai/knowledge/page`, params })
  18 + },
  19 +
  20 + // 查询知识库详情
  21 + getKnowledge: async (id: number) => {
  22 + return await request.get({ url: `/ai/knowledge/get?id=` + id })
  23 + },
  24 +
  25 + // 新增知识库
  26 + createKnowledge: async (data: KnowledgeVO) => {
  27 + return await request.post({ url: `/ai/knowledge/create`, data })
  28 + },
  29 +
  30 + // 修改知识库
  31 + updateKnowledge: async (data: KnowledgeVO) => {
  32 + return await request.put({ url: `/ai/knowledge/update`, data })
  33 + },
  34 +
  35 + // 删除知识库
  36 + deleteKnowledge: async (id: number) => {
  37 + return await request.delete({ url: `/ai/knowledge/delete?id=` + id })
  38 + },
  39 +
  40 + // 获取知识库简单列表
  41 + getSimpleKnowledgeList: async () => {
  42 + return await request.get({ url: `/ai/knowledge/simple-list` })
  43 + }
  44 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 知识库分段 VO
  4 +export interface KnowledgeSegmentVO {
  5 + id: number // 编号
  6 + documentId: number // 文档编号
  7 + knowledgeId: number // 知识库编号
  8 + vectorId: string // 向量库编号
  9 + content: string // 切片内容
  10 + contentLength: number // 切片内容长度
  11 + tokens: number // token 数量
  12 + retrievalCount: number // 召回次数
  13 + status: number // 文档状态
  14 + createTime: number // 创建时间
  15 +}
  16 +
  17 +// AI 知识库分段 API
  18 +export const KnowledgeSegmentApi = {
  19 + // 查询知识库分段分页
  20 + getKnowledgeSegmentPage: async (params: any) => {
  21 + return await request.get({ url: `/ai/knowledge/segment/page`, params })
  22 + },
  23 +
  24 + // 查询知识库分段详情
  25 + getKnowledgeSegment: async (id: number) => {
  26 + return await request.get({ url: `/ai/knowledge/segment/get?id=` + id })
  27 + },
  28 +
  29 + // 删除知识库分段
  30 + deleteKnowledgeSegment: async (id: number) => {
  31 + return await request.delete({ url: `/ai/knowledge/segment/delete?id=` + id })
  32 + },
  33 +
  34 + // 新增知识库分段
  35 + createKnowledgeSegment: async (data: KnowledgeSegmentVO) => {
  36 + return await request.post({ url: `/ai/knowledge/segment/create`, data })
  37 + },
  38 +
  39 + // 修改知识库分段
  40 + updateKnowledgeSegment: async (data: KnowledgeSegmentVO) => {
  41 + return await request.put({ url: `/ai/knowledge/segment/update`, data })
  42 + },
  43 +
  44 + // 修改知识库分段状态
  45 + updateKnowledgeSegmentStatus: async (data: any) => {
  46 + return await request.put({
  47 + url: `/ai/knowledge/segment/update-status`,
  48 + data
  49 + })
  50 + },
  51 +
  52 + // 切片内容
  53 + splitContent: async (url: string, segmentMaxTokens: number) => {
  54 + return await request.get({
  55 + url: `/ai/knowledge/segment/split`,
  56 + params: { url, segmentMaxTokens }
  57 + })
  58 + },
  59 +
  60 + // 获取文档处理列表
  61 + getKnowledgeSegmentProcessList: async (documentIds: number[]) => {
  62 + return await request.get({
  63 + url: `/ai/knowledge/segment/get-process-list`,
  64 + params: { documentIds: documentIds.join(',') }
  65 + })
  66 + },
  67 +
  68 + // 搜索知识库分段
  69 + searchKnowledgeSegment: async (params: any) => {
  70 + return await request.get({
  71 + url: `/ai/knowledge/segment/search`,
  72 + params
  73 + })
  74 + }
  75 +}
  1 +import { getAccessToken } from '@/utils/auth'
  2 +import { fetchEventSource } from '@microsoft/fetch-event-source'
  3 +import { config } from '@/config/axios/config'
  4 +import request from '@/config/axios' // AI 思维导图 VO
  5 +
  6 +// AI 思维导图 VO
  7 +export interface MindMapVO {
  8 + id: number // 编号
  9 + userId: number // 用户编号
  10 + prompt: string // 生成内容提示
  11 + generatedContent: string // 生成的思维导图内容
  12 + platform: string // 平台
  13 + model: string // 模型
  14 + errorMessage: string // 错误信息
  15 +}
  16 +
  17 +// AI 思维导图生成 VO
  18 +export interface AiMindMapGenerateReqVO {
  19 + prompt: string
  20 +}
  21 +
  22 +export const AiMindMapApi = {
  23 + generateMindMap: ({
  24 + data,
  25 + onClose,
  26 + onMessage,
  27 + onError,
  28 + ctrl
  29 + }: {
  30 + data: AiMindMapGenerateReqVO
  31 + onMessage?: (res: any) => void
  32 + onError?: (...args: any[]) => void
  33 + onClose?: (...args: any[]) => void
  34 + ctrl: AbortController
  35 + }) => {
  36 + const token = getAccessToken()
  37 + return fetchEventSource(`${config.base_url}/ai/mind-map/generate-stream`, {
  38 + method: 'post',
  39 + headers: {
  40 + 'Content-Type': 'application/json',
  41 + Authorization: `Bearer ${token}`
  42 + },
  43 + openWhenHidden: true,
  44 + body: JSON.stringify(data),
  45 + onmessage: onMessage,
  46 + onerror: onError,
  47 + onclose: onClose,
  48 + signal: ctrl.signal
  49 + })
  50 + },
  51 +
  52 + // 查询思维导图分页
  53 + getMindMapPage: async (params: any) => {
  54 + return await request.get({ url: `/ai/mind-map/page`, params })
  55 + },
  56 + // 删除思维导图
  57 + deleteMindMap: async (id: number) => {
  58 + return await request.delete({ url: `/ai/mind-map/delete?id=` + id })
  59 + }
  60 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI API 密钥 VO
  4 +export interface ApiKeyVO {
  5 + id: number // 编号
  6 + name: string // 名称
  7 + apiKey: string // 密钥
  8 + platform: string // 平台
  9 + url: string // 自定义 API 地址
  10 + status: number // 状态
  11 +}
  12 +
  13 +// AI API 密钥 API
  14 +export const ApiKeyApi = {
  15 + // 查询 API 密钥分页
  16 + getApiKeyPage: async (params: any) => {
  17 + return await request.get({ url: `/ai/api-key/page`, params })
  18 + },
  19 +
  20 + // 获得 API 密钥列表
  21 + getApiKeySimpleList: async () => {
  22 + return await request.get({ url: `/ai/api-key/simple-list` })
  23 + },
  24 +
  25 + // 查询 API 密钥详情
  26 + getApiKey: async (id: number) => {
  27 + return await request.get({ url: `/ai/api-key/get?id=` + id })
  28 + },
  29 +
  30 + // 新增 API 密钥
  31 + createApiKey: async (data: ApiKeyVO) => {
  32 + return await request.post({ url: `/ai/api-key/create`, data })
  33 + },
  34 +
  35 + // 修改 API 密钥
  36 + updateApiKey: async (data: ApiKeyVO) => {
  37 + return await request.put({ url: `/ai/api-key/update`, data })
  38 + },
  39 +
  40 + // 删除 API 密钥
  41 + deleteApiKey: async (id: number) => {
  42 + return await request.delete({ url: `/ai/api-key/delete?id=` + id })
  43 + }
  44 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 聊天角色 VO
  4 +export interface ChatRoleVO {
  5 + id: number // 角色编号
  6 + modelId: number // 模型编号
  7 + name: string // 角色名称
  8 + avatar: string // 角色头像
  9 + category: string // 角色类别
  10 + sort: number // 角色排序
  11 + description: string // 角色描述
  12 + systemMessage: string // 角色设定
  13 + welcomeMessage: string // 角色设定
  14 + publicStatus: boolean // 是否公开
  15 + status: number // 状态
  16 + knowledgeIds?: number[] // 引用的知识库 ID 列表
  17 + toolIds?: number[] // 引用的工具 ID 列表
  18 + mcpClientNames?: string[] // 引用的 MCP Client 名字列表
  19 +}
  20 +
  21 +// AI 聊天角色 分页请求 vo
  22 +export interface ChatRolePageReqVO {
  23 + name?: string // 角色名称
  24 + category?: string // 角色类别
  25 + publicStatus: boolean // 是否公开
  26 + pageNo: number // 是否公开
  27 + pageSize: number // 是否公开
  28 +}
  29 +
  30 +// AI 聊天角色 API
  31 +export const ChatRoleApi = {
  32 + // 查询聊天角色分页
  33 + getChatRolePage: async (params: any) => {
  34 + return await request.get({ url: `/ai/chat-role/page`, params })
  35 + },
  36 +
  37 + // 查询聊天角色详情
  38 + getChatRole: async (id: number) => {
  39 + return await request.get({ url: `/ai/chat-role/get?id=` + id })
  40 + },
  41 +
  42 + // 新增聊天角色
  43 + createChatRole: async (data: ChatRoleVO) => {
  44 + return await request.post({ url: `/ai/chat-role/create`, data })
  45 + },
  46 +
  47 + // 修改聊天角色
  48 + updateChatRole: async (data: ChatRoleVO) => {
  49 + return await request.put({ url: `/ai/chat-role/update`, data })
  50 + },
  51 +
  52 + // 删除聊天角色
  53 + deleteChatRole: async (id: number) => {
  54 + return await request.delete({ url: `/ai/chat-role/delete?id=` + id })
  55 + },
  56 +
  57 + // ======= chat 聊天
  58 +
  59 + // 获取 my role
  60 + getMyPage: async (params: ChatRolePageReqVO) => {
  61 + return await request.get({ url: `/ai/chat-role/my-page`, params })
  62 + },
  63 +
  64 + // 获取角色分类
  65 + getCategoryList: async () => {
  66 + return await request.get({ url: `/ai/chat-role/category-list` })
  67 + },
  68 +
  69 + // 创建角色
  70 + createMy: async (data: ChatRoleVO) => {
  71 + return await request.post({ url: `/ai/chat-role/create-my`, data })
  72 + },
  73 +
  74 + // 更新角色
  75 + updateMy: async (data: ChatRoleVO) => {
  76 + return await request.put({ url: `/ai/chat-role/update-my`, data })
  77 + },
  78 +
  79 + // 删除角色 my
  80 + deleteMy: async (id: number) => {
  81 + return await request.delete({ url: `/ai/chat-role/delete-my?id=` + id })
  82 + }
  83 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 模型 VO
  4 +export interface ModelVO {
  5 + id: number // 编号
  6 + keyId: number // API 秘钥编号
  7 + name: string // 模型名字
  8 + model: string // 模型标识
  9 + platform: string // 模型平台
  10 + type: number // 模型类型
  11 + sort: number // 排序
  12 + status: number // 状态
  13 + temperature?: number // 温度参数
  14 + maxTokens?: number // 单条回复的最大 Token 数量
  15 + maxContexts?: number // 上下文的最大 Message 数量
  16 +}
  17 +
  18 +// AI 模型 API
  19 +export const ModelApi = {
  20 + // 查询模型分页
  21 + getModelPage: async (params: any) => {
  22 + return await request.get({ url: `/ai/model/page`, params })
  23 + },
  24 +
  25 + // 获得模型列表
  26 + getModelSimpleList: async (type?: number) => {
  27 + return await request.get({
  28 + url: `/ai/model/simple-list`,
  29 + params: {
  30 + type
  31 + }
  32 + })
  33 + },
  34 +
  35 + // 查询模型详情
  36 + getModel: async (id: number) => {
  37 + return await request.get({ url: `/ai/model/get?id=` + id })
  38 + },
  39 +
  40 + // 新增模型
  41 + createModel: async (data: ModelVO) => {
  42 + return await request.post({ url: `/ai/model/create`, data })
  43 + },
  44 +
  45 + // 修改模型
  46 + updateModel: async (data: ModelVO) => {
  47 + return await request.put({ url: `/ai/model/update`, data })
  48 + },
  49 +
  50 + // 删除模型
  51 + deleteModel: async (id: number) => {
  52 + return await request.delete({ url: `/ai/model/delete?id=` + id })
  53 + }
  54 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 工具 VO
  4 +export interface ToolVO {
  5 + id: number // 工具编号
  6 + name: string // 工具名称
  7 + description: string // 工具描述
  8 + status: number // 状态
  9 +}
  10 +
  11 +// AI 工具 API
  12 +export const ToolApi = {
  13 + // 查询工具分页
  14 + getToolPage: async (params: any) => {
  15 + return await request.get({ url: `/ai/tool/page`, params })
  16 + },
  17 +
  18 + // 查询工具详情
  19 + getTool: async (id: number) => {
  20 + return await request.get({ url: `/ai/tool/get?id=` + id })
  21 + },
  22 +
  23 + // 新增工具
  24 + createTool: async (data: ToolVO) => {
  25 + return await request.post({ url: `/ai/tool/create`, data })
  26 + },
  27 +
  28 + // 修改工具
  29 + updateTool: async (data: ToolVO) => {
  30 + return await request.put({ url: `/ai/tool/update`, data })
  31 + },
  32 +
  33 + // 删除工具
  34 + deleteTool: async (id: number) => {
  35 + return await request.delete({ url: `/ai/tool/delete?id=` + id })
  36 + },
  37 +
  38 + // 获取工具简单列表
  39 + getToolSimpleList: async () => {
  40 + return await request.get({ url: `/ai/tool/simple-list` })
  41 + }
  42 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// AI 音乐 VO
  4 +export interface MusicVO {
  5 + id: number // 编号
  6 + userId: number // 用户编号
  7 + title: string // 音乐名称
  8 + lyric: string // 歌词
  9 + imageUrl: string // 图片地址
  10 + audioUrl: string // 音频地址
  11 + videoUrl: string // 视频地址
  12 + status: number // 音乐状态
  13 + gptDescriptionPrompt: string // 描述词
  14 + prompt: string // 提示词
  15 + platform: string // 模型平台
  16 + model: string // 模型
  17 + generateMode: number // 生成模式
  18 + tags: string // 音乐风格标签
  19 + duration: number // 音乐时长
  20 + publicStatus: boolean // 是否发布
  21 + taskId: string // 任务id
  22 + errorMessage: string // 错误信息
  23 +}
  24 +
  25 +// AI 音乐 API
  26 +export const MusicApi = {
  27 + // 查询音乐分页
  28 + getMusicPage: async (params: any) => {
  29 + return await request.get({ url: `/ai/music/page`, params })
  30 + },
  31 +
  32 + // 更新音乐
  33 + updateMusic: async (data: any) => {
  34 + return await request.put({ url: '/ai/music/update', data })
  35 + },
  36 +
  37 + // 删除音乐
  38 + deleteMusic: async (id: number) => {
  39 + return await request.delete({ url: `/ai/music/delete?id=` + id })
  40 + }
  41 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export const getWorkflowPage = async (params) => {
  4 + return await request.get({ url: '/ai/workflow/page', params })
  5 +}
  6 +
  7 +export const getWorkflow = async (id) => {
  8 + return await request.get({ url: '/ai/workflow/get?id=' + id })
  9 +}
  10 +
  11 +export const createWorkflow = async (data) => {
  12 + return await request.post({ url: '/ai/workflow/create', data })
  13 +}
  14 +
  15 +export const updateWorkflow = async (data) => {
  16 + return await request.put({ url: '/ai/workflow/update', data })
  17 +}
  18 +
  19 +export const deleteWorkflow = async (id) => {
  20 + return await request.delete({ url: '/ai/workflow/delete?id=' + id })
  21 +}
  22 +
  23 +export const testWorkflow = async (data) => {
  24 + return await request.post({ url: '/ai/workflow/test', data })
  25 +}
  1 +import { fetchEventSource } from '@microsoft/fetch-event-source'
  2 +
  3 +import { getAccessToken } from '@/utils/auth'
  4 +import { config } from '@/config/axios/config'
  5 +import { AiWriteTypeEnum } from '@/views/ai/utils/constants'
  6 +import request from '@/config/axios'
  7 +
  8 +export interface WriteVO {
  9 + type: AiWriteTypeEnum.WRITING | AiWriteTypeEnum.REPLY // 1:撰写 2:回复
  10 + prompt: string // 写作内容提示 1。撰写 2回复
  11 + originalContent: string // 原文
  12 + length: number // 长度
  13 + format: number // 格式
  14 + tone: number // 语气
  15 + language: number // 语言
  16 + userId?: number // 用户编号
  17 + platform?: string // 平台
  18 + model?: string // 模型
  19 + generatedContent?: string // 生成的内容
  20 + errorMessage?: string // 错误信息
  21 + createTime?: Date // 创建时间
  22 +}
  23 +
  24 +export interface AiWritePageReqVO extends PageParam {
  25 + userId?: number // 用户编号
  26 + type?: AiWriteTypeEnum // 写作类型
  27 + platform?: string // 平台
  28 + createTime?: [string, string] // 创建时间
  29 +}
  30 +
  31 +export interface AiWriteRespVo {
  32 + id: number
  33 + userId: number
  34 + type: number
  35 + platform: string
  36 + model: string
  37 + prompt: string
  38 + generatedContent: string
  39 + originalContent: string
  40 + length: number
  41 + format: number
  42 + tone: number
  43 + language: number
  44 + errorMessage: string
  45 + createTime: string
  46 +}
  47 +
  48 +export const WriteApi = {
  49 + writeStream: ({
  50 + data,
  51 + onClose,
  52 + onMessage,
  53 + onError,
  54 + ctrl
  55 + }: {
  56 + data: WriteVO
  57 + onMessage?: (res: any) => void
  58 + onError?: (...args: any[]) => void
  59 + onClose?: (...args: any[]) => void
  60 + ctrl: AbortController
  61 + }) => {
  62 + const token = getAccessToken()
  63 + return fetchEventSource(`${config.base_url}/ai/write/generate-stream`, {
  64 + method: 'post',
  65 + headers: {
  66 + 'Content-Type': 'application/json',
  67 + Authorization: `Bearer ${token}`
  68 + },
  69 + openWhenHidden: true,
  70 + body: JSON.stringify(data),
  71 + onmessage: onMessage,
  72 + onerror: onError,
  73 + onclose: onClose,
  74 + signal: ctrl.signal
  75 + })
  76 + },
  77 + // 获取写作列表
  78 + getWritePage: (params: AiWritePageReqVO) => {
  79 + return request.get<PageResult<AiWriteRespVo[]>>({ url: `/ai/write/page`, params })
  80 + },
  81 + // 删除写作
  82 + deleteWrite(id: number) {
  83 + return request.delete({ url: `/ai/write/delete`, params: { id } })
  84 + }
  85 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// BPM 流程分类 VO
  4 +export interface CategoryVO {
  5 + id: number // 分类编号
  6 + name: string // 分类名
  7 + code: string // 分类标志
  8 + status: number // 分类状态
  9 + sort: number // 分类排序
  10 +}
  11 +
  12 +// BPM 流程分类 API
  13 +export const CategoryApi = {
  14 + // 查询流程分类分页
  15 + getCategoryPage: async (params: any) => {
  16 + return await request.get({ url: `/bpm/category/page`, params })
  17 + },
  18 +
  19 + // 查询流程分类列表
  20 + getCategorySimpleList: async () => {
  21 + return await request.get({ url: `/bpm/category/simple-list` })
  22 + },
  23 +
  24 + // 查询流程分类详情
  25 + getCategory: async (id: number) => {
  26 + return await request.get({ url: `/bpm/category/get?id=` + id })
  27 + },
  28 +
  29 + // 新增流程分类
  30 + createCategory: async (data: CategoryVO) => {
  31 + return await request.post({ url: `/bpm/category/create`, data })
  32 + },
  33 +
  34 + // 修改流程分类
  35 + updateCategory: async (data: CategoryVO) => {
  36 + return await request.put({ url: `/bpm/category/update`, data })
  37 + },
  38 +
  39 + // 批量修改流程分类的排序
  40 + updateCategorySortBatch: async (ids: number[]) => {
  41 + return await request.put({
  42 + url: `/bpm/category/update-sort-batch`,
  43 + params: {
  44 + ids: ids.join(',')
  45 + }
  46 + })
  47 + },
  48 +
  49 + // 删除流程分类
  50 + deleteCategory: async (id: number) => {
  51 + return await request.delete({ url: `/bpm/category/delete?id=` + id })
  52 + }
  53 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export const getProcessDefinition = async (id?: string, key?: string) => {
  4 + return await request.get({
  5 + url: '/bpm/process-definition/get',
  6 + params: { id, key }
  7 + })
  8 +}
  9 +
  10 +export const getProcessDefinitionPage = async (params) => {
  11 + return await request.get({
  12 + url: '/bpm/process-definition/page',
  13 + params
  14 + })
  15 +}
  16 +
  17 +export const getProcessDefinitionList = async (params) => {
  18 + return await request.get({
  19 + url: '/bpm/process-definition/list',
  20 + params
  21 + })
  22 +}
  23 +
  24 +export const getSimpleProcessDefinitionList = async () => {
  25 + return await request.get({
  26 + url: '/bpm/process-definition/simple-list'
  27 + })
  28 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export type FormVO = {
  4 + id: number
  5 + name: string
  6 + conf: string
  7 + fields: string[]
  8 + status: number
  9 + remark: string
  10 + createTime: string
  11 +}
  12 +
  13 +// 创建工作流的表单定义
  14 +export const createForm = async (data: FormVO) => {
  15 + return await request.post({
  16 + url: '/bpm/form/create',
  17 + data: data
  18 + })
  19 +}
  20 +
  21 +// 更新工作流的表单定义
  22 +export const updateForm = async (data: FormVO) => {
  23 + return await request.put({
  24 + url: '/bpm/form/update',
  25 + data: data
  26 + })
  27 +}
  28 +
  29 +// 删除工作流的表单定义
  30 +export const deleteForm = async (id: number) => {
  31 + return await request.delete({
  32 + url: '/bpm/form/delete?id=' + id
  33 + })
  34 +}
  35 +
  36 +// 获得工作流的表单定义
  37 +export const getForm = async (id: number) => {
  38 + return await request.get({
  39 + url: '/bpm/form/get?id=' + id
  40 + })
  41 +}
  42 +
  43 +// 获得工作流的表单定义分页
  44 +export const getFormPage = async (params) => {
  45 + return await request.get({
  46 + url: '/bpm/form/page',
  47 + params
  48 + })
  49 +}
  50 +
  51 +// 获得动态表单的精简列表
  52 +export const getFormSimpleList = async () => {
  53 + return await request.get({
  54 + url: '/bpm/form/simple-list'
  55 + })
  56 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export type LeaveVO = {
  4 + id: number
  5 + status: number
  6 + type: number
  7 + reason: string
  8 + processInstanceId: string
  9 + startTime: string
  10 + endTime: string
  11 + createTime: string
  12 +}
  13 +
  14 +// 创建请假申请
  15 +export const createLeave = async (data: LeaveVO) => {
  16 + return await request.post({ url: '/bpm/oa/leave/create', data: data })
  17 +}
  18 +
  19 +// 获得请假申请
  20 +export const getLeave = async (id: number) => {
  21 + return await request.get({ url: '/bpm/oa/leave/get?id=' + id })
  22 +}
  23 +
  24 +// 获得请假申请分页
  25 +export const getLeavePage = async (params: PageParam) => {
  26 + return await request.get({ url: '/bpm/oa/leave/page', params })
  27 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export type ProcessDefinitionVO = {
  4 + id: string
  5 + version: number
  6 + deploymentTIme: string
  7 + suspensionState: number
  8 + formType?: number
  9 +}
  10 +
  11 +export type ModelVO = {
  12 + id: number
  13 + formName: string
  14 + key: string
  15 + name: string
  16 + description: string
  17 + category: string
  18 + formType: number
  19 + formId: number
  20 + formCustomCreatePath: string
  21 + formCustomViewPath: string
  22 + processDefinition: ProcessDefinitionVO
  23 + status: number
  24 + remark: string
  25 + createTime: string
  26 + bpmnXml: string
  27 +}
  28 +
  29 +export const getModelList = async (name: string | undefined) => {
  30 + return await request.get({ url: '/bpm/model/list', params: { name } })
  31 +}
  32 +
  33 +export const getModel = async (id: string) => {
  34 + return await request.get({ url: '/bpm/model/get?id=' + id })
  35 +}
  36 +
  37 +export const updateModel = async (data: ModelVO) => {
  38 + return await request.put({ url: '/bpm/model/update', data: data })
  39 +}
  40 +
  41 +// 批量修改流程分类的排序
  42 +export const updateModelSortBatch = async (ids: number[]) => {
  43 + return await request.put({
  44 + url: `/bpm/model/update-sort-batch`,
  45 + params: {
  46 + ids: ids.join(',')
  47 + }
  48 + })
  49 +}
  50 +
  51 +export const updateModelBpmn = async (data: ModelVO) => {
  52 + return await request.put({ url: '/bpm/model/update-bpmn', data: data })
  53 +}
  54 +
  55 +// 任务状态修改
  56 +export const updateModelState = async (id: number, state: number) => {
  57 + const data = {
  58 + id: id,
  59 + state: state
  60 + }
  61 + return await request.put({ url: '/bpm/model/update-state', data: data })
  62 +}
  63 +
  64 +export const createModel = async (data: ModelVO) => {
  65 + return await request.post({ url: '/bpm/model/create', data: data })
  66 +}
  67 +
  68 +export const deleteModel = async (id: number) => {
  69 + return await request.delete({ url: '/bpm/model/delete?id=' + id })
  70 +}
  71 +
  72 +export const deployModel = async (id: number) => {
  73 + return await request.post({ url: '/bpm/model/deploy?id=' + id })
  74 +}
  75 +
  76 +export const cleanModel = async (id: number) => {
  77 + return await request.delete({ url: '/bpm/model/clean?id=' + id })
  78 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// BPM 流程表达式 VO
  4 +export interface ProcessExpressionVO {
  5 + id: number // 编号
  6 + name: string // 表达式名字
  7 + status: number // 表达式状态
  8 + expression: string // 表达式
  9 +}
  10 +
  11 +// BPM 流程表达式 API
  12 +export const ProcessExpressionApi = {
  13 + // 查询BPM 流程表达式分页
  14 + getProcessExpressionPage: async (params: any) => {
  15 + return await request.get({ url: `/bpm/process-expression/page`, params })
  16 + },
  17 +
  18 + // 查询BPM 流程表达式详情
  19 + getProcessExpression: async (id: number) => {
  20 + return await request.get({ url: `/bpm/process-expression/get?id=` + id })
  21 + },
  22 +
  23 + // 新增BPM 流程表达式
  24 + createProcessExpression: async (data: ProcessExpressionVO) => {
  25 + return await request.post({ url: `/bpm/process-expression/create`, data })
  26 + },
  27 +
  28 + // 修改BPM 流程表达式
  29 + updateProcessExpression: async (data: ProcessExpressionVO) => {
  30 + return await request.put({ url: `/bpm/process-expression/update`, data })
  31 + },
  32 +
  33 + // 删除BPM 流程表达式
  34 + deleteProcessExpression: async (id: number) => {
  35 + return await request.delete({ url: `/bpm/process-expression/delete?id=` + id })
  36 + },
  37 +
  38 + // 导出BPM 流程表达式 Excel
  39 + exportProcessExpression: async (params) => {
  40 + return await request.download({ url: `/bpm/process-expression/export-excel`, params })
  41 + }
  42 +}
  1 +import request from '@/config/axios'
  2 +import { ProcessDefinitionVO } from '@/api/bpm/model'
  3 +import { NodeType, CandidateStrategy } from '@/components/SimpleProcessDesignerV2/src/consts'
  4 +export type Task = {
  5 + id: string
  6 + name: string
  7 +}
  8 +
  9 +export type ProcessInstanceVO = {
  10 + id: number
  11 + name: string
  12 + processDefinitionId: string
  13 + category: string
  14 + result: number
  15 + tasks: Task[]
  16 + fields: string[]
  17 + status: number
  18 + remark: string
  19 + businessKey: string
  20 + createTime: string
  21 + endTime: string
  22 + processDefinition?: ProcessDefinitionVO
  23 +}
  24 +
  25 +// 用户信息
  26 +export type User = {
  27 + id: number
  28 + nickname: string
  29 + avatar: string
  30 +}
  31 +
  32 +// 审批任务信息
  33 +export type ApprovalTaskInfo = {
  34 + id: number
  35 + ownerUser: User
  36 + assigneeUser: User
  37 + status: number
  38 + reason: string
  39 + signPicUrl: string
  40 +}
  41 +
  42 +// 审批节点信息
  43 +export type ApprovalNodeInfo = {
  44 + id: number
  45 + name: string
  46 + nodeType: NodeType
  47 + candidateStrategy?: CandidateStrategy
  48 + status: number
  49 + startTime?: Date
  50 + endTime?: Date
  51 + processInstanceId?: string
  52 + candidateUsers?: User[]
  53 + tasks: ApprovalTaskInfo[]
  54 +}
  55 +
  56 +export const getProcessInstanceMyPage = async (params: any) => {
  57 + return await request.get({ url: '/bpm/process-instance/my-page', params })
  58 +}
  59 +
  60 +export const getProcessInstanceManagerPage = async (params: any) => {
  61 + return await request.get({ url: '/bpm/process-instance/manager-page', params })
  62 +}
  63 +
  64 +export const createProcessInstance = async (data) => {
  65 + return await request.post({ url: '/bpm/process-instance/create', data: data })
  66 +}
  67 +
  68 +export const cancelProcessInstanceByStartUser = async (id: number, reason: string) => {
  69 + const data = {
  70 + id: id,
  71 + reason: reason
  72 + }
  73 + return await request.delete({ url: '/bpm/process-instance/cancel-by-start-user', data: data })
  74 +}
  75 +
  76 +export const cancelProcessInstanceByAdmin = async (id: number, reason: string) => {
  77 + const data = {
  78 + id: id,
  79 + reason: reason
  80 + }
  81 + return await request.delete({ url: '/bpm/process-instance/cancel-by-admin', data: data })
  82 +}
  83 +
  84 +export const getProcessInstance = async (id: string) => {
  85 + return await request.get({ url: '/bpm/process-instance/get?id=' + id })
  86 +}
  87 +
  88 +export const getProcessInstanceCopyPage = async (params: any) => {
  89 + return await request.get({ url: '/bpm/process-instance/copy/page', params })
  90 +}
  91 +
  92 +// 获取审批详情
  93 +export const getApprovalDetail = async (params: any) => {
  94 + return await request.get({ url: '/bpm/process-instance/get-approval-detail', params })
  95 +}
  96 +
  97 +// 获取下一个执行的流程节点
  98 +export const getNextApprovalNodes = async (params: any) => {
  99 + return await request.get({ url: '/bpm/process-instance/get-next-approval-nodes', params })
  100 +}
  101 +
  102 +// 获取表单字段权限
  103 +export const getFormFieldsPermission = async (params: any) => {
  104 + return await request.get({ url: '/bpm/process-instance/get-form-fields-permission', params })
  105 +}
  106 +
  107 +// 获取流程实例的 BPMN 模型视图
  108 +export const getProcessInstanceBpmnModelView = async (id: string) => {
  109 + return await request.get({ url: '/bpm/process-instance/get-bpmn-model-view?id=' + id })
  110 +}
  111 +
  112 +// 获取流程实例打印数据
  113 +export const getProcessInstancePrintData = async (id: string) => {
  114 + return await request.get({ url: '/bpm/process-instance/get-print-data?processInstanceId=' + id })
  115 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// BPM 流程监听器 VO
  4 +export interface ProcessListenerVO {
  5 + id: number // 编号
  6 + name: string // 监听器名字
  7 + type: string // 监听器类型
  8 + status: number // 监听器状态
  9 + event: string // 监听事件
  10 + valueType: string // 监听器值类型
  11 + value: string // 监听器值
  12 +}
  13 +
  14 +// BPM 流程监听器 API
  15 +export const ProcessListenerApi = {
  16 + // 查询流程监听器分页
  17 + getProcessListenerPage: async (params: any) => {
  18 + return await request.get({ url: `/bpm/process-listener/page`, params })
  19 + },
  20 +
  21 + // 查询流程监听器详情
  22 + getProcessListener: async (id: number) => {
  23 + return await request.get({ url: `/bpm/process-listener/get?id=` + id })
  24 + },
  25 +
  26 + // 新增流程监听器
  27 + createProcessListener: async (data: ProcessListenerVO) => {
  28 + return await request.post({ url: `/bpm/process-listener/create`, data })
  29 + },
  30 +
  31 + // 修改流程监听器
  32 + updateProcessListener: async (data: ProcessListenerVO) => {
  33 + return await request.put({ url: `/bpm/process-listener/update`, data })
  34 + },
  35 +
  36 + // 删除流程监听器
  37 + deleteProcessListener: async (id: number) => {
  38 + return await request.delete({ url: `/bpm/process-listener/delete?id=` + id })
  39 + }
  40 +}
  1 +import request from '@/config/axios'
  2 +
  3 +
  4 +export const updateBpmSimpleModel = async (data) => {
  5 + return await request.post({
  6 + url: '/bpm/model/simple/update',
  7 + data: data
  8 + })
  9 +}
  10 +
  11 +export const getBpmSimpleModel = async (id) => {
  12 + return await request.get({
  13 + url: '/bpm/model/simple/get?id=' + id
  14 + })
  15 +}
  1 +import request from '@/config/axios'
  2 +
  3 +/**
  4 + * 任务状态枚举
  5 + */
  6 +export enum TaskStatusEnum {
  7 + /**
  8 + * 跳过
  9 + */
  10 + SKIP = -2,
  11 + /**
  12 + * 未开始
  13 + */
  14 + NOT_START = -1,
  15 +
  16 + /**
  17 + * 待审批
  18 + */
  19 + WAIT = 0,
  20 + /**
  21 + * 审批中
  22 + */
  23 + RUNNING = 1,
  24 + /**
  25 + * 审批通过
  26 + */
  27 + APPROVE = 2,
  28 +
  29 + /**
  30 + * 审批不通过
  31 + */
  32 + REJECT = 3,
  33 +
  34 + /**
  35 + * 已取消
  36 + */
  37 + CANCEL = 4,
  38 + /**
  39 + * 已退回
  40 + */
  41 + RETURN = 5,
  42 + /**
  43 + * 审批通过中
  44 + */
  45 + APPROVING = 7
  46 +}
  47 +
  48 +export const getTaskTodoPage = async (params: any) => {
  49 + return await request.get({ url: '/bpm/task/todo-page', params })
  50 +}
  51 +
  52 +export const getTaskDonePage = async (params: any) => {
  53 + return await request.get({ url: '/bpm/task/done-page', params })
  54 +}
  55 +
  56 +export const getTaskManagerPage = async (params: any) => {
  57 + return await request.get({ url: '/bpm/task/manager-page', params })
  58 +}
  59 +
  60 +export const approveTask = async (data: any) => {
  61 + return await request.put({ url: '/bpm/task/approve', data })
  62 +}
  63 +
  64 +export const rejectTask = async (data: any) => {
  65 + return await request.put({ url: '/bpm/task/reject', data })
  66 +}
  67 +
  68 +export const getTaskListByProcessInstanceId = async (processInstanceId: string) => {
  69 + return await request.get({
  70 + url: '/bpm/task/list-by-process-instance-id?processInstanceId=' + processInstanceId
  71 + })
  72 +}
  73 +
  74 +// 获取所有可退回的节点
  75 +export const getTaskListByReturn = async (id: string) => {
  76 + return await request.get({ url: '/bpm/task/list-by-return', params: { id } })
  77 +}
  78 +
  79 +// 退回
  80 +export const returnTask = async (data: any) => {
  81 + return await request.put({ url: '/bpm/task/return', data })
  82 +}
  83 +
  84 +// 委派
  85 +export const delegateTask = async (data: any) => {
  86 + return await request.put({ url: '/bpm/task/delegate', data })
  87 +}
  88 +
  89 +// 转派
  90 +export const transferTask = async (data: any) => {
  91 + return await request.put({ url: '/bpm/task/transfer', data })
  92 +}
  93 +
  94 +// 加签
  95 +export const signCreateTask = async (data: any) => {
  96 + return await request.put({ url: '/bpm/task/create-sign', data })
  97 +}
  98 +
  99 +// 减签
  100 +export const signDeleteTask = async (data: any) => {
  101 + return await request.delete({ url: '/bpm/task/delete-sign', data })
  102 +}
  103 +
  104 +// 抄送
  105 +export const copyTask = async (data: any) => {
  106 + return await request.put({ url: '/bpm/task/copy', data })
  107 +}
  108 +
  109 +// 撤回
  110 +export const withdrawTask = async (taskId: string) => {
  111 + return await request.put({ url: '/bpm/task/withdraw', params: { taskId } })
  112 +}
  113 +
  114 +// 获取我的待办任务
  115 +export const myTodoTask = async (processInstanceId: string) => {
  116 + return await request.get({ url: '/bpm/task/my-todo?processInstanceId=' + processInstanceId })
  117 +}
  118 +
  119 +// 获取减签任务列表
  120 +export const getChildrenTaskList = async (id: string) => {
  121 + return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id })
  122 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export type UserGroupVO = {
  4 + id: number
  5 + name: string
  6 + description: string
  7 + userIds: number[]
  8 + status: number
  9 + remark: string
  10 + createTime: string
  11 +}
  12 +
  13 +// 创建用户组
  14 +export const createUserGroup = async (data: UserGroupVO) => {
  15 + return await request.post({
  16 + url: '/bpm/user-group/create',
  17 + data: data
  18 + })
  19 +}
  20 +
  21 +// 更新用户组
  22 +export const updateUserGroup = async (data: UserGroupVO) => {
  23 + return await request.put({
  24 + url: '/bpm/user-group/update',
  25 + data: data
  26 + })
  27 +}
  28 +
  29 +// 删除用户组
  30 +export const deleteUserGroup = async (id: number) => {
  31 + return await request.delete({ url: '/bpm/user-group/delete?id=' + id })
  32 +}
  33 +
  34 +// 获得用户组
  35 +export const getUserGroup = async (id: number) => {
  36 + return await request.get({ url: '/bpm/user-group/get?id=' + id })
  37 +}
  38 +
  39 +// 获得用户组分页
  40 +export const getUserGroupPage = async (params) => {
  41 + return await request.get({ url: '/bpm/user-group/page', params })
  42 +}
  43 +
  44 +// 获取用户组精简信息列表
  45 +export const getUserGroupSimpleList = async (): Promise<UserGroupVO[]> => {
  46 + return await request.get({ url: '/bpm/user-group/simple-list' })
  47 +}
  1 +import request from '@/config/axios'
  2 +import { TransferReqVO } from '@/api/crm/permission'
  3 +
  4 +export interface BusinessVO {
  5 + id: number
  6 + name: string
  7 + customerId: number
  8 + customerName?: string
  9 + followUpStatus: boolean
  10 + contactLastTime: Date
  11 + contactNextTime: Date
  12 + ownerUserId: number
  13 + ownerUserName?: string // 负责人的用户名称
  14 + ownerUserDept?: string // 负责人的部门名称
  15 + statusTypeId: number
  16 + statusTypeName?: string
  17 + statusId: number
  18 + statusName?: string
  19 + endStatus: number
  20 + endRemark: string
  21 + dealTime: Date
  22 + totalProductPrice: number
  23 + totalPrice: number
  24 + discountPercent: number
  25 + remark: string
  26 + creator: string // 创建人
  27 + creatorName?: string // 创建人名称
  28 + createTime: Date // 创建时间
  29 + updateTime: Date // 更新时间
  30 + products?: [
  31 + {
  32 + id: number
  33 + productId: number
  34 + productName: string
  35 + productNo: string
  36 + productUnit: number
  37 + productPrice: number
  38 + businessPrice: number
  39 + count: number
  40 + totalPrice: number
  41 + }
  42 + ]
  43 +}
  44 +
  45 +// 查询 CRM 商机列表
  46 +export const getBusinessPage = async (params) => {
  47 + return await request.get({ url: `/crm/business/page`, params })
  48 +}
  49 +
  50 +// 查询 CRM 商机列表,基于指定客户
  51 +export const getBusinessPageByCustomer = async (params) => {
  52 + return await request.get({ url: `/crm/business/page-by-customer`, params })
  53 +}
  54 +
  55 +// 查询 CRM 商机详情
  56 +export const getBusiness = async (id: number) => {
  57 + return await request.get({ url: `/crm/business/get?id=` + id })
  58 +}
  59 +
  60 +// 获得 CRM 商机列表(精简)
  61 +export const getSimpleBusinessList = async () => {
  62 + return await request.get({ url: `/crm/business/simple-all-list` })
  63 +}
  64 +
  65 +// 新增 CRM 商机
  66 +export const createBusiness = async (data: BusinessVO) => {
  67 + return await request.post({ url: `/crm/business/create`, data })
  68 +}
  69 +
  70 +// 修改 CRM 商机
  71 +export const updateBusiness = async (data: BusinessVO) => {
  72 + return await request.put({ url: `/crm/business/update`, data })
  73 +}
  74 +
  75 +// 修改 CRM 商机状态
  76 +export const updateBusinessStatus = async (data: BusinessVO) => {
  77 + return await request.put({ url: `/crm/business/update-status`, data })
  78 +}
  79 +
  80 +// 删除 CRM 商机
  81 +export const deleteBusiness = async (id: number) => {
  82 + return await request.delete({ url: `/crm/business/delete?id=` + id })
  83 +}
  84 +
  85 +// 导出 CRM 商机 Excel
  86 +export const exportBusiness = async (params) => {
  87 + return await request.download({ url: `/crm/business/export-excel`, params })
  88 +}
  89 +
  90 +// 联系人关联商机列表
  91 +export const getBusinessPageByContact = async (params) => {
  92 + return await request.get({ url: `/crm/business/page-by-contact`, params })
  93 +}
  94 +
  95 +// 商机转移
  96 +export const transferBusiness = async (data: TransferReqVO) => {
  97 + return await request.put({ url: '/crm/business/transfer', data })
  98 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface BusinessStatusTypeVO {
  4 + id: number
  5 + name: string
  6 + deptIds: number[]
  7 + statuses?: {
  8 + id: number
  9 + name: string
  10 + percent: number
  11 + }
  12 +}
  13 +
  14 +export const DEFAULT_STATUSES = [
  15 + {
  16 + endStatus: 1,
  17 + key: '结束',
  18 + name: '赢单',
  19 + percent: 100
  20 + },
  21 + {
  22 + endStatus: 2,
  23 + key: '结束',
  24 + name: '输单',
  25 + percent: 0
  26 + },
  27 + {
  28 + endStatus: 3,
  29 + key: '结束',
  30 + name: '无效',
  31 + percent: 0
  32 + }
  33 +]
  34 +
  35 +// 查询商机状态组列表
  36 +export const getBusinessStatusPage = async (params: any) => {
  37 + return await request.get({ url: `/crm/business-status/page`, params })
  38 +}
  39 +
  40 +// 新增商机状态组
  41 +export const createBusinessStatus = async (data: BusinessStatusTypeVO) => {
  42 + return await request.post({ url: `/crm/business-status/create`, data })
  43 +}
  44 +
  45 +// 修改商机状态组
  46 +export const updateBusinessStatus = async (data: BusinessStatusTypeVO) => {
  47 + return await request.put({ url: `/crm/business-status/update`, data })
  48 +}
  49 +
  50 +// 查询商机状态类型详情
  51 +export const getBusinessStatus = async (id: number) => {
  52 + return await request.get({ url: `/crm/business-status/get?id=` + id })
  53 +}
  54 +
  55 +// 删除商机状态
  56 +export const deleteBusinessStatus = async (id: number) => {
  57 + return await request.delete({ url: `/crm/business-status/delete?id=` + id })
  58 +}
  59 +
  60 +// 获得商机状态组列表
  61 +export const getBusinessStatusTypeSimpleList = async () => {
  62 + return await request.get({ url: `/crm/business-status/type-simple-list` })
  63 +}
  64 +
  65 +// 获得商机阶段列表
  66 +export const getBusinessStatusSimpleList = async (typeId: number) => {
  67 + return await request.get({ url: `/crm/business-status/status-simple-list`, params: { typeId } })
  68 +}
  1 +import request from '@/config/axios'
  2 +import { TransferReqVO } from '@/api/crm/permission'
  3 +
  4 +export interface ClueVO {
  5 + id: number // 编号
  6 + name: string // 线索名称
  7 + followUpStatus: boolean // 跟进状态
  8 + contactLastTime: Date // 最后跟进时间
  9 + contactLastContent: string // 最后跟进内容
  10 + contactNextTime: Date // 下次联系时间
  11 + ownerUserId: number // 负责人的用户编号
  12 + ownerUserName?: string // 负责人的用户名称
  13 + ownerUserDept?: string // 负责人的部门名称
  14 + transformStatus: boolean // 转化状态
  15 + customerId: number // 客户编号
  16 + customerName?: string // 客户名称
  17 + mobile: string // 手机号
  18 + telephone: string // 电话
  19 + qq: string // QQ
  20 + wechat: string // wechat
  21 + email: string // email
  22 + areaId: number // 所在地
  23 + areaName?: string // 所在地名称
  24 + detailAddress: string // 详细地址
  25 + industryId: number // 所属行业
  26 + level: number // 客户等级
  27 + source: number // 客户来源
  28 + remark: string // 备注
  29 + creator: string // 创建人
  30 + creatorName?: string // 创建人名称
  31 + createTime: Date // 创建时间
  32 + updateTime: Date // 更新时间
  33 +}
  34 +
  35 +// 查询线索列表
  36 +export const getCluePage = async (params: any) => {
  37 + return await request.get({ url: `/crm/clue/page`, params })
  38 +}
  39 +
  40 +// 查询线索详情
  41 +export const getClue = async (id: number) => {
  42 + return await request.get({ url: `/crm/clue/get?id=` + id })
  43 +}
  44 +
  45 +// 新增线索
  46 +export const createClue = async (data: ClueVO) => {
  47 + return await request.post({ url: `/crm/clue/create`, data })
  48 +}
  49 +
  50 +// 修改线索
  51 +export const updateClue = async (data: ClueVO) => {
  52 + return await request.put({ url: `/crm/clue/update`, data })
  53 +}
  54 +
  55 +// 删除线索
  56 +export const deleteClue = async (id: number) => {
  57 + return await request.delete({ url: `/crm/clue/delete?id=` + id })
  58 +}
  59 +
  60 +// 导出线索 Excel
  61 +export const exportClue = async (params) => {
  62 + return await request.download({ url: `/crm/clue/export-excel`, params })
  63 +}
  64 +
  65 +// 线索转移
  66 +export const transferClue = async (data: TransferReqVO) => {
  67 + return await request.put({ url: '/crm/clue/transfer', data })
  68 +}
  69 +
  70 +// 线索转化为客户
  71 +export const transformClue = async (id: number) => {
  72 + return await request.put({ url: '/crm/clue/transform', params: { id } })
  73 +}
  74 +
  75 +// 获得分配给我的、待跟进的线索数量
  76 +export const getFollowClueCount = async () => {
  77 + return await request.get({ url: '/crm/clue/follow-count' })
  78 +}
  1 +import request from '@/config/axios'
  2 +import { TransferReqVO } from '@/api/crm/permission'
  3 +
  4 +export interface ContactVO {
  5 + id: number // 编号
  6 + name: string // 联系人名称
  7 + customerId: number // 客户编号
  8 + customerName?: string // 客户名称
  9 + contactLastTime: Date // 最后跟进时间
  10 + contactLastContent: string // 最后跟进内容
  11 + contactNextTime: Date // 下次联系时间
  12 + ownerUserId: number // 负责人的用户编号
  13 + ownerUserName?: string // 负责人的用户名称
  14 + ownerUserDept?: string // 负责人的部门名称
  15 + mobile: string // 手机号
  16 + telephone: string // 电话
  17 + qq: string // QQ
  18 + wechat: string // wechat
  19 + email: string // email
  20 + areaId: number // 所在地
  21 + areaName?: string // 所在地名称
  22 + detailAddress: string // 详细地址
  23 + sex: number // 性别
  24 + master: boolean // 是否主联系人
  25 + post: string // 职务
  26 + parentId: number // 上级联系人编号
  27 + parentName?: string // 上级联系人名称
  28 + remark: string // 备注
  29 + creator: string // 创建人
  30 + creatorName?: string // 创建人名称
  31 + createTime: Date // 创建时间
  32 + updateTime: Date // 更新时间
  33 +}
  34 +
  35 +export interface ContactBusinessReqVO {
  36 + contactId: number
  37 + businessIds: number[]
  38 +}
  39 +
  40 +export interface ContactBusiness2ReqVO {
  41 + businessId: number
  42 + contactIds: number[]
  43 +}
  44 +
  45 +// 查询 CRM 联系人列表
  46 +export const getContactPage = async (params) => {
  47 + return await request.get({ url: `/crm/contact/page`, params })
  48 +}
  49 +
  50 +// 查询 CRM 联系人列表,基于指定客户
  51 +export const getContactPageByCustomer = async (params: any) => {
  52 + return await request.get({ url: `/crm/contact/page-by-customer`, params })
  53 +}
  54 +
  55 +// 查询 CRM 联系人列表,基于指定商机
  56 +export const getContactPageByBusiness = async (params: any) => {
  57 + return await request.get({ url: `/crm/contact/page-by-business`, params })
  58 +}
  59 +
  60 +// 查询 CRM 联系人详情
  61 +export const getContact = async (id: number) => {
  62 + return await request.get({ url: `/crm/contact/get?id=` + id })
  63 +}
  64 +
  65 +// 新增 CRM 联系人
  66 +export const createContact = async (data: ContactVO) => {
  67 + return await request.post({ url: `/crm/contact/create`, data })
  68 +}
  69 +
  70 +// 修改 CRM 联系人
  71 +export const updateContact = async (data: ContactVO) => {
  72 + return await request.put({ url: `/crm/contact/update`, data })
  73 +}
  74 +
  75 +// 删除 CRM 联系人
  76 +export const deleteContact = async (id: number) => {
  77 + return await request.delete({ url: `/crm/contact/delete?id=` + id })
  78 +}
  79 +
  80 +// 导出 CRM 联系人 Excel
  81 +export const exportContact = async (params) => {
  82 + return await request.download({ url: `/crm/contact/export-excel`, params })
  83 +}
  84 +
  85 +// 获得 CRM 联系人列表(精简)
  86 +export const getSimpleContactList = async () => {
  87 + return await request.get({ url: `/crm/contact/simple-all-list` })
  88 +}
  89 +
  90 +// 批量新增联系人商机关联
  91 +export const createContactBusinessList = async (data: ContactBusinessReqVO) => {
  92 + return await request.post({ url: `/crm/contact/create-business-list`, data })
  93 +}
  94 +
  95 +// 批量新增联系人商机关联
  96 +export const createContactBusinessList2 = async (data: ContactBusiness2ReqVO) => {
  97 + return await request.post({ url: `/crm/contact/create-business-list2`, data })
  98 +}
  99 +
  100 +// 解除联系人商机关联
  101 +export const deleteContactBusinessList = async (data: ContactBusinessReqVO) => {
  102 + return await request.delete({ url: `/crm/contact/delete-business-list`, data })
  103 +}
  104 +
  105 +// 解除联系人商机关联
  106 +export const deleteContactBusinessList2 = async (data: ContactBusiness2ReqVO) => {
  107 + return await request.delete({ url: `/crm/contact/delete-business-list2`, data })
  108 +}
  109 +
  110 +// 联系人转移
  111 +export const transferContact = async (data: TransferReqVO) => {
  112 + return await request.put({ url: '/crm/contact/transfer', data })
  113 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface ContractConfigVO {
  4 + notifyEnabled?: boolean
  5 + notifyDays?: number
  6 +}
  7 +
  8 +// 获取合同配置
  9 +export const getContractConfig = async () => {
  10 + return await request.get({ url: `/crm/contract-config/get` })
  11 +}
  12 +
  13 +// 更新合同配置
  14 +export const saveContractConfig = async (data: ContractConfigVO) => {
  15 + return await request.put({ url: `/crm/contract-config/save`, data })
  16 +}
  1 +import request from '@/config/axios'
  2 +import { TransferReqVO } from '@/api/crm/permission'
  3 +
  4 +export interface ContractVO {
  5 + id: number
  6 + name: string
  7 + no: string
  8 + customerId: number
  9 + customerName?: string
  10 + businessId: number
  11 + businessName: string
  12 + contactLastTime: Date
  13 + ownerUserId: number
  14 + ownerUserName?: string
  15 + ownerUserDeptName?: string
  16 + processInstanceId: number
  17 + auditStatus: number
  18 + orderDate: Date
  19 + startTime: Date
  20 + endTime: Date
  21 + totalProductPrice: number
  22 + discountPercent: number
  23 + totalPrice: number
  24 + totalReceivablePrice: number
  25 + signContactId: number
  26 + signContactName?: string
  27 + signUserId: number
  28 + signUserName: string
  29 + remark: string
  30 + createTime?: Date
  31 + creator: string
  32 + creatorName: string
  33 + updateTime?: Date
  34 + products?: [
  35 + {
  36 + id: number
  37 + productId: number
  38 + productName: string
  39 + productNo: string
  40 + productUnit: number
  41 + productPrice: number
  42 + contractPrice: number
  43 + count: number
  44 + totalPrice: number
  45 + }
  46 + ]
  47 +}
  48 +
  49 +// 查询 CRM 合同列表
  50 +export const getContractPage = async (params) => {
  51 + return await request.get({ url: `/crm/contract/page`, params })
  52 +}
  53 +
  54 +// 查询 CRM 联系人列表,基于指定客户
  55 +export const getContractPageByCustomer = async (params: any) => {
  56 + return await request.get({ url: `/crm/contract/page-by-customer`, params })
  57 +}
  58 +
  59 +// 查询 CRM 联系人列表,基于指定商机
  60 +export const getContractPageByBusiness = async (params: any) => {
  61 + return await request.get({ url: `/crm/contract/page-by-business`, params })
  62 +}
  63 +
  64 +// 查询 CRM 合同详情
  65 +export const getContract = async (id: number) => {
  66 + return await request.get({ url: `/crm/contract/get?id=` + id })
  67 +}
  68 +
  69 +// 查询 CRM 合同下拉列表
  70 +export const getContractSimpleList = async (customerId: number) => {
  71 + return await request.get({
  72 + url: `/crm/contract/simple-list?customerId=${customerId}`
  73 + })
  74 +}
  75 +
  76 +// 新增 CRM 合同
  77 +export const createContract = async (data: ContractVO) => {
  78 + return await request.post({ url: `/crm/contract/create`, data })
  79 +}
  80 +
  81 +// 修改 CRM 合同
  82 +export const updateContract = async (data: ContractVO) => {
  83 + return await request.put({ url: `/crm/contract/update`, data })
  84 +}
  85 +
  86 +// 删除 CRM 合同
  87 +export const deleteContract = async (id: number) => {
  88 + return await request.delete({ url: `/crm/contract/delete?id=` + id })
  89 +}
  90 +
  91 +// 导出 CRM 合同 Excel
  92 +export const exportContract = async (params) => {
  93 + return await request.download({ url: `/crm/contract/export-excel`, params })
  94 +}
  95 +
  96 +// 提交审核
  97 +export const submitContract = async (id: number) => {
  98 + return await request.put({ url: `/crm/contract/submit?id=${id}` })
  99 +}
  100 +
  101 +// 合同转移
  102 +export const transferContract = async (data: TransferReqVO) => {
  103 + return await request.put({ url: '/crm/contract/transfer', data })
  104 +}
  105 +
  106 +// 获得待审核合同数量
  107 +export const getAuditContractCount = async () => {
  108 + return await request.get({ url: '/crm/contract/audit-count' })
  109 +}
  110 +
  111 +// 获得即将到期(提醒)的合同数量
  112 +export const getRemindContractCount = async () => {
  113 + return await request.get({ url: '/crm/contract/remind-count' })
  114 +}
  1 +import request from '@/config/axios'
  2 +import { TransferReqVO } from '@/api/crm/permission'
  3 +
  4 +export interface CustomerVO {
  5 + id: number // 编号
  6 + name: string // 客户名称
  7 + followUpStatus: boolean // 跟进状态
  8 + contactLastTime: Date // 最后跟进时间
  9 + contactLastContent: string // 最后跟进内容
  10 + contactNextTime: Date // 下次联系时间
  11 + ownerUserId: number // 负责人的用户编号
  12 + ownerUserName?: string // 负责人的用户名称
  13 + ownerUserDept?: string // 负责人的部门名称
  14 + lockStatus?: boolean
  15 + dealStatus?: boolean
  16 + mobile: string // 手机号
  17 + telephone: string // 电话
  18 + qq: string // QQ
  19 + wechat: string // wechat
  20 + email: string // email
  21 + areaId: number // 所在地
  22 + areaName?: string // 所在地名称
  23 + detailAddress: string // 详细地址
  24 + industryId: number // 所属行业
  25 + level: number // 客户等级
  26 + source: number // 客户来源
  27 + remark: string // 备注
  28 + creator: string // 创建人
  29 + creatorName?: string // 创建人名称
  30 + createTime: Date // 创建时间
  31 + updateTime: Date // 更新时间
  32 +}
  33 +
  34 +// 查询客户列表
  35 +export const getCustomerPage = async (params) => {
  36 + return await request.get({ url: `/crm/customer/page`, params })
  37 +}
  38 +
  39 +// 进入公海客户提醒的客户列表
  40 +export const getPutPoolRemindCustomerPage = async (params) => {
  41 + return await request.get({ url: `/crm/customer/put-pool-remind-page`, params })
  42 +}
  43 +
  44 +// 获得待进入公海客户数量
  45 +export const getPutPoolRemindCustomerCount = async () => {
  46 + return await request.get({ url: `/crm/customer/put-pool-remind-count` })
  47 +}
  48 +
  49 +// 获得今日需联系客户数量
  50 +export const getTodayContactCustomerCount = async () => {
  51 + return await request.get({ url: `/crm/customer/today-contact-count` })
  52 +}
  53 +
  54 +// 获得分配给我、待跟进的线索数量的客户数量
  55 +export const getFollowCustomerCount = async () => {
  56 + return await request.get({ url: `/crm/customer/follow-count` })
  57 +}
  58 +
  59 +// 查询客户详情
  60 +export const getCustomer = async (id: number) => {
  61 + return await request.get({ url: `/crm/customer/get?id=` + id })
  62 +}
  63 +
  64 +// 新增客户
  65 +export const createCustomer = async (data: CustomerVO) => {
  66 + return await request.post({ url: `/crm/customer/create`, data })
  67 +}
  68 +
  69 +// 修改客户
  70 +export const updateCustomer = async (data: CustomerVO) => {
  71 + return await request.put({ url: `/crm/customer/update`, data })
  72 +}
  73 +
  74 +// 更新客户的成交状态
  75 +export const updateCustomerDealStatus = async (id: number, dealStatus: boolean) => {
  76 + return await request.put({ url: `/crm/customer/update-deal-status`, params: { id, dealStatus } })
  77 +}
  78 +
  79 +// 删除客户
  80 +export const deleteCustomer = async (id: number) => {
  81 + return await request.delete({ url: `/crm/customer/delete?id=` + id })
  82 +}
  83 +
  84 +// 导出客户 Excel
  85 +export const exportCustomer = async (params: any) => {
  86 + return await request.download({ url: `/crm/customer/export-excel`, params })
  87 +}
  88 +
  89 +// 下载客户导入模板
  90 +export const importCustomerTemplate = () => {
  91 + return request.download({ url: '/crm/customer/get-import-template' })
  92 +}
  93 +
  94 +// 导入客户
  95 +export const handleImport = async (formData) => {
  96 + return await request.upload({ url: `/crm/customer/import`, data: formData })
  97 +}
  98 +
  99 +// 客户列表
  100 +export const getCustomerSimpleList = async () => {
  101 + return await request.get({ url: `/crm/customer/simple-list` })
  102 +}
  103 +
  104 +// ======================= 业务操作 =======================
  105 +
  106 +// 客户转移
  107 +export const transferCustomer = async (data: TransferReqVO) => {
  108 + return await request.put({ url: '/crm/customer/transfer', data })
  109 +}
  110 +
  111 +// 锁定/解锁客户
  112 +export const lockCustomer = async (id: number, lockStatus: boolean) => {
  113 + return await request.put({ url: `/crm/customer/lock`, data: { id, lockStatus } })
  114 +}
  115 +
  116 +// 领取公海客户
  117 +export const receiveCustomer = async (ids: any[]) => {
  118 + return await request.put({ url: '/crm/customer/receive', params: { ids: ids.join(',') } })
  119 +}
  120 +
  121 +// 分配公海给对应负责人
  122 +export const distributeCustomer = async (ids: any[], ownerUserId: number) => {
  123 + return await request.put({
  124 + url: '/crm/customer/distribute',
  125 + data: { ids: ids, ownerUserId }
  126 + })
  127 +}
  128 +
  129 +// 客户放入公海
  130 +export const putCustomerPool = async (id: number) => {
  131 + return await request.put({ url: `/crm/customer/put-pool?id=${id}` })
  132 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface CustomerLimitConfigVO {
  4 + id?: number
  5 + type?: number
  6 + userIds?: string
  7 + deptIds?: string
  8 + maxCount?: number
  9 + dealCountEnabled?: boolean
  10 +}
  11 +
  12 +/**
  13 + * 客户限制配置类型
  14 + */
  15 +export enum LimitConfType {
  16 + /**
  17 + * 拥有客户数限制
  18 + */
  19 + CUSTOMER_QUANTITY_LIMIT = 1,
  20 + /**
  21 + * 锁定客户数限制
  22 + */
  23 + CUSTOMER_LOCK_LIMIT = 2
  24 +}
  25 +
  26 +// 查询客户限制配置列表
  27 +export const getCustomerLimitConfigPage = async (params) => {
  28 + return await request.get({ url: `/crm/customer-limit-config/page`, params })
  29 +}
  30 +
  31 +// 查询客户限制配置详情
  32 +export const getCustomerLimitConfig = async (id: number) => {
  33 + return await request.get({ url: `/crm/customer-limit-config/get?id=` + id })
  34 +}
  35 +
  36 +// 新增客户限制配置
  37 +export const createCustomerLimitConfig = async (data: CustomerLimitConfigVO) => {
  38 + return await request.post({ url: `/crm/customer-limit-config/create`, data })
  39 +}
  40 +
  41 +// 修改客户限制配置
  42 +export const updateCustomerLimitConfig = async (data: CustomerLimitConfigVO) => {
  43 + return await request.put({ url: `/crm/customer-limit-config/update`, data })
  44 +}
  45 +
  46 +// 删除客户限制配置
  47 +export const deleteCustomerLimitConfig = async (id: number) => {
  48 + return await request.delete({ url: `/crm/customer-limit-config/delete?id=` + id })
  49 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface CustomerPoolConfigVO {
  4 + enabled?: boolean
  5 + contactExpireDays?: number
  6 + dealExpireDays?: number
  7 + notifyEnabled?: boolean
  8 + notifyDays?: number
  9 +}
  10 +
  11 +// 获取客户公海规则设置
  12 +export const getCustomerPoolConfig = async () => {
  13 + return await request.get({ url: `/crm/customer-pool-config/get` })
  14 +}
  15 +
  16 +// 更新客户公海规则设置
  17 +export const saveCustomerPoolConfig = async (data: CustomerPoolConfigVO) => {
  18 + return await request.put({ url: `/crm/customer-pool-config/save`, data })
  19 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// 跟进记录 VO
  4 +export interface FollowUpRecordVO {
  5 + id: number // 编号
  6 + bizType: number // 数据类型
  7 + bizId: number // 数据编号
  8 + type: number // 跟进类型
  9 + content: string // 跟进内容
  10 + picUrls: string[] // 图片
  11 + fileUrls: string[] // 附件
  12 + nextTime: Date // 下次联系时间
  13 + businessIds: number[] // 关联的商机编号数组
  14 + businesses: {
  15 + id: number
  16 + name: string
  17 + }[] // 关联的商机数组
  18 + contactIds: number[] // 关联的联系人编号数组
  19 + contacts: {
  20 + id: number
  21 + name: string
  22 + }[] // 关联的联系人数组
  23 + creator: string
  24 + creatorName?: string
  25 +}
  26 +
  27 +// 跟进记录 API
  28 +export const FollowUpRecordApi = {
  29 + // 查询跟进记录分页
  30 + getFollowUpRecordPage: async (params: any) => {
  31 + return await request.get({ url: `/crm/follow-up-record/page`, params })
  32 + },
  33 +
  34 + // 新增跟进记录
  35 + createFollowUpRecord: async (data: FollowUpRecordVO) => {
  36 + return await request.post({ url: `/crm/follow-up-record/create`, data })
  37 + },
  38 +
  39 + // 删除跟进记录
  40 + deleteFollowUpRecord: async (id: number) => {
  41 + return await request.delete({ url: `/crm/follow-up-record/delete?id=` + id })
  42 + }
  43 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface OperateLogVO extends PageParam {
  4 + bizType: number
  5 + bizId: number
  6 +}
  7 +
  8 +// 获得操作日志
  9 +export const getOperateLogPage = async (params: OperateLogVO) => {
  10 + return await request.get({ url: `/crm/operate-log/page`, params })
  11 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface PermissionVO {
  4 + id?: number // 数据权限编号
  5 + userId: number // 用户编号
  6 + bizType: number // Crm 类型
  7 + bizId: number // Crm 类型数据编号
  8 + level: number // 权限级别
  9 + toBizTypes?: number[] // 同时添加至
  10 + deptName?: string // 部门名称
  11 + nickname?: string // 用户昵称
  12 + postNames?: string[] // 岗位名称数组
  13 + createTime?: Date
  14 + ids?: number[]
  15 +}
  16 +
  17 +export interface TransferReqVO {
  18 + id: number // 模块编号
  19 + newOwnerUserId: number // 新负责人的用户编号
  20 + oldOwnerPermissionLevel?: number // 老负责人加入团队后的权限级别
  21 + toBizTypes?: number[] // 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择
  22 +}
  23 +
  24 +/**
  25 + * CRM 业务类型枚举
  26 + *
  27 + * @author HUIHUI
  28 + */
  29 +export enum BizTypeEnum {
  30 + CRM_CLUE = 1, // 线索
  31 + CRM_CUSTOMER = 2, // 客户
  32 + CRM_CONTACT = 3, // 联系人
  33 + CRM_BUSINESS = 4, // 商机
  34 + CRM_CONTRACT = 5, // 合同
  35 + CRM_PRODUCT = 6, // 产品
  36 + CRM_RECEIVABLE = 7, // 回款
  37 + CRM_RECEIVABLE_PLAN = 8 // 回款计划
  38 +}
  39 +
  40 +/**
  41 + * CRM 数据权限级别枚举
  42 + */
  43 +export enum PermissionLevelEnum {
  44 + OWNER = 1, // 负责人
  45 + READ = 2, // 只读
  46 + WRITE = 3 // 读写
  47 +}
  48 +
  49 +// 获得数据权限列表(查询团队成员列表)
  50 +export const getPermissionList = async (params) => {
  51 + return await request.get({ url: `/crm/permission/list`, params })
  52 +}
  53 +
  54 +// 创建数据权限(新增团队成员)
  55 +export const createPermission = async (data: PermissionVO) => {
  56 + return await request.post({ url: `/crm/permission/create`, data })
  57 +}
  58 +
  59 +// 编辑数据权限(修改团队成员权限级别)
  60 +export const updatePermission = async (data) => {
  61 + return await request.put({ url: `/crm/permission/update`, data })
  62 +}
  63 +
  64 +// 删除数据权限(删除团队成员)
  65 +export const deletePermissionBatch = async (val: number[]) => {
  66 + return await request.delete({ url: '/crm/permission/delete?ids=' + val.join(',') })
  67 +}
  68 +
  69 +// 删除自己的数据权限(退出团队)
  70 +export const deleteSelfPermission = async (id: number) => {
  71 + return await request.delete({ url: '/crm/permission/delete-self?id=' + id })
  72 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// TODO @zange:挪到 product 下,建个 category 包,挪进去哈;
  4 +export interface ProductCategoryVO {
  5 + id: number
  6 + name: string
  7 + parentId: number
  8 +}
  9 +
  10 +// 查询产品分类详情
  11 +export const getProductCategory = async (id: number) => {
  12 + return await request.get({ url: `/crm/product-category/get?id=` + id })
  13 +}
  14 +
  15 +// 新增产品分类
  16 +export const createProductCategory = async (data: ProductCategoryVO) => {
  17 + return await request.post({ url: `/crm/product-category/create`, data })
  18 +}
  19 +
  20 +// 修改产品分类
  21 +export const updateProductCategory = async (data: ProductCategoryVO) => {
  22 + return await request.put({ url: `/crm/product-category/update`, data })
  23 +}
  24 +
  25 +// 删除产品分类
  26 +export const deleteProductCategory = async (id: number) => {
  27 + return await request.delete({ url: `/crm/product-category/delete?id=` + id })
  28 +}
  29 +
  30 +// 产品分类列表
  31 +export const getProductCategoryList = async (params) => {
  32 + return await request.get({ url: `/crm/product-category/list`, params })
  33 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface ProductVO {
  4 + id: number
  5 + name: string
  6 + no: string
  7 + unit: number
  8 + price: number
  9 + status: number
  10 + categoryId: number
  11 + categoryName?: string
  12 + description: string
  13 + ownerUserId: number
  14 +}
  15 +
  16 +// 查询产品列表
  17 +export const getProductPage = async (params) => {
  18 + return await request.get({ url: `/crm/product/page`, params })
  19 +}
  20 +
  21 +// 获得产品精简列表
  22 +export const getProductSimpleList = async () => {
  23 + return await request.get({ url: `/crm/product/simple-list` })
  24 +}
  25 +
  26 +// 查询产品详情
  27 +export const getProduct = async (id: number) => {
  28 + return await request.get({ url: `/crm/product/get?id=` + id })
  29 +}
  30 +
  31 +// 新增产品
  32 +export const createProduct = async (data: ProductVO) => {
  33 + return await request.post({ url: `/crm/product/create`, data })
  34 +}
  35 +
  36 +// 修改产品
  37 +export const updateProduct = async (data: ProductVO) => {
  38 + return await request.put({ url: `/crm/product/update`, data })
  39 +}
  40 +
  41 +// 删除产品
  42 +export const deleteProduct = async (id: number) => {
  43 + return await request.delete({ url: `/crm/product/delete?id=` + id })
  44 +}
  45 +
  46 +// 导出产品 Excel
  47 +export const exportProduct = async (params) => {
  48 + return await request.download({ url: `/crm/product/export-excel`, params })
  49 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface ReceivableVO {
  4 + id: number
  5 + no: string
  6 + planId?: number
  7 + customerId?: number
  8 + customerName?: string
  9 + contractId?: number
  10 + contract?: {
  11 + id?: number
  12 + name?: string
  13 + no: string
  14 + totalPrice: number
  15 + }
  16 + auditStatus: number
  17 + processInstanceId: number
  18 + returnTime: Date
  19 + returnType: number
  20 + price: number
  21 + ownerUserId: number
  22 + ownerUserName?: string
  23 + remark: string
  24 + creator: string // 创建人
  25 + creatorName?: string // 创建人名称
  26 + createTime: Date // 创建时间
  27 + updateTime: Date // 更新时间
  28 +}
  29 +
  30 +// 查询回款列表
  31 +export const getReceivablePage = async (params) => {
  32 + return await request.get({ url: `/crm/receivable/page`, params })
  33 +}
  34 +
  35 +// 查询回款列表
  36 +export const getReceivablePageByCustomer = async (params) => {
  37 + return await request.get({ url: `/crm/receivable/page-by-customer`, params })
  38 +}
  39 +
  40 +// 查询回款详情
  41 +export const getReceivable = async (id: number) => {
  42 + return await request.get({ url: `/crm/receivable/get?id=` + id })
  43 +}
  44 +
  45 +// 新增回款
  46 +export const createReceivable = async (data: ReceivableVO) => {
  47 + return await request.post({ url: `/crm/receivable/create`, data })
  48 +}
  49 +
  50 +// 修改回款
  51 +export const updateReceivable = async (data: ReceivableVO) => {
  52 + return await request.put({ url: `/crm/receivable/update`, data })
  53 +}
  54 +
  55 +// 删除回款
  56 +export const deleteReceivable = async (id: number) => {
  57 + return await request.delete({ url: `/crm/receivable/delete?id=` + id })
  58 +}
  59 +
  60 +// 导出回款 Excel
  61 +export const exportReceivable = async (params) => {
  62 + return await request.download({ url: `/crm/receivable/export-excel`, params })
  63 +}
  64 +
  65 +// 提交审核
  66 +export const submitReceivable = async (id: number) => {
  67 + return await request.put({ url: `/crm/receivable/submit?id=${id}` })
  68 +}
  69 +
  70 +// 获得待审核回款数量
  71 +export const getAuditReceivableCount = async () => {
  72 + return await request.get({ url: '/crm/receivable/audit-count' })
  73 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface ReceivablePlanVO {
  4 + id: number
  5 + period: number
  6 + receivableId: number
  7 + price: number
  8 + returnTime: Date
  9 + remindDays: number
  10 + returnType: number
  11 + remindTime: Date
  12 + customerId: number
  13 + customerName?: string
  14 + contractId?: number
  15 + contractNo?: string
  16 + ownerUserId: number
  17 + ownerUserName?: string
  18 + remark: string
  19 + creator: string // 创建人
  20 + creatorName?: string // 创建人名称
  21 + createTime: Date // 创建时间
  22 + updateTime: Date // 更新时间
  23 + receivable?: {
  24 + price: number
  25 + returnTime: Date
  26 + }
  27 +}
  28 +
  29 +// 查询回款计划列表
  30 +export const getReceivablePlanPage = async (params) => {
  31 + return await request.get({ url: `/crm/receivable-plan/page`, params })
  32 +}
  33 +
  34 +// 查询回款计划列表
  35 +export const getReceivablePlanPageByCustomer = async (params) => {
  36 + return await request.get({ url: `/crm/receivable-plan/page-by-customer`, params })
  37 +}
  38 +
  39 +// 查询回款计划详情
  40 +export const getReceivablePlan = async (id: number) => {
  41 + return await request.get({ url: `/crm/receivable-plan/get?id=` + id })
  42 +}
  43 +
  44 +// 查询回款计划下拉数据
  45 +export const getReceivablePlanSimpleList = async (customerId: number, contractId: number) => {
  46 + return await request.get({
  47 + url: `/crm/receivable-plan/simple-list?customerId=${customerId}&contractId=${contractId}`
  48 + })
  49 +}
  50 +
  51 +// 新增回款计划
  52 +export const createReceivablePlan = async (data: ReceivablePlanVO) => {
  53 + return await request.post({ url: `/crm/receivable-plan/create`, data })
  54 +}
  55 +
  56 +// 修改回款计划
  57 +export const updateReceivablePlan = async (data: ReceivablePlanVO) => {
  58 + return await request.put({ url: `/crm/receivable-plan/update`, data })
  59 +}
  60 +
  61 +// 删除回款计划
  62 +export const deleteReceivablePlan = async (id: number) => {
  63 + return await request.delete({ url: `/crm/receivable-plan/delete?id=` + id })
  64 +}
  65 +
  66 +// 导出回款计划 Excel
  67 +export const exportReceivablePlan = async (params) => {
  68 + return await request.download({ url: `/crm/receivable-plan/export-excel`, params })
  69 +}
  70 +
  71 +// 获得待回款提醒数量
  72 +export const getReceivablePlanRemindCount = async () => {
  73 + return await request.get({ url: '/crm/receivable-plan/remind-count' })
  74 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface CrmStatisticsCustomerSummaryByDateRespVO {
  4 + time: string
  5 + customerCreateCount: number
  6 + customerDealCount: number
  7 +}
  8 +
  9 +export interface CrmStatisticsCustomerSummaryByUserRespVO {
  10 + ownerUserName: string
  11 + customerCreateCount: number
  12 + customerDealCount: number
  13 + contractPrice: number
  14 + receivablePrice: number
  15 +}
  16 +
  17 +export interface CrmStatisticsFollowUpSummaryByDateRespVO {
  18 + time: string
  19 + followUpRecordCount: number
  20 + followUpCustomerCount: number
  21 +}
  22 +
  23 +export interface CrmStatisticsFollowUpSummaryByUserRespVO {
  24 + ownerUserName: string
  25 + followupRecordCount: number
  26 + followupCustomerCount: number
  27 +}
  28 +
  29 +export interface CrmStatisticsFollowUpSummaryByTypeRespVO {
  30 + followUpType: string
  31 + followUpRecordCount: number
  32 +}
  33 +
  34 +export interface CrmStatisticsCustomerContractSummaryRespVO {
  35 + customerName: string
  36 + contractName: string
  37 + totalPrice: number
  38 + receivablePrice: number
  39 + customerType: string
  40 + customerSource: string
  41 + ownerUserName: string
  42 + creatorUserName: string
  43 + createTime: Date
  44 + orderDate: Date
  45 +}
  46 +
  47 +export interface CrmStatisticsPoolSummaryByDateRespVO {
  48 + time: string
  49 + customerPutCount: number
  50 + customerTakeCount: number
  51 +}
  52 +
  53 +export interface CrmStatisticsPoolSummaryByUserRespVO {
  54 + ownerUserName: string
  55 + customerPutCount: number
  56 + customerTakeCount: number
  57 +}
  58 +
  59 +export interface CrmStatisticsCustomerDealCycleByDateRespVO {
  60 + time: string
  61 + customerDealCycle: number
  62 +}
  63 +
  64 +export interface CrmStatisticsCustomerDealCycleByUserRespVO {
  65 + ownerUserName: string
  66 + customerDealCycle: number
  67 + customerDealCount: number
  68 +}
  69 +
  70 +export interface CrmStatisticsCustomerDealCycleByAreaRespVO {
  71 + areaName: string
  72 + customerDealCycle: number
  73 + customerDealCount: number
  74 +}
  75 +
  76 +export interface CrmStatisticsCustomerDealCycleByProductRespVO {
  77 + productName: string
  78 + customerDealCycle: number
  79 + customerDealCount: number
  80 +}
  81 +
  82 +// 客户分析 API
  83 +export const StatisticsCustomerApi = {
  84 + // 1.1 客户总量分析(按日期)
  85 + getCustomerSummaryByDate: (params: any) => {
  86 + return request.get({
  87 + url: '/crm/statistics-customer/get-customer-summary-by-date',
  88 + params
  89 + })
  90 + },
  91 + // 1.2 客户总量分析(按用户)
  92 + getCustomerSummaryByUser: (params: any) => {
  93 + return request.get({
  94 + url: '/crm/statistics-customer/get-customer-summary-by-user',
  95 + params
  96 + })
  97 + },
  98 + // 2.1 客户跟进次数分析(按日期)
  99 + getFollowUpSummaryByDate: (params: any) => {
  100 + return request.get({
  101 + url: '/crm/statistics-customer/get-follow-up-summary-by-date',
  102 + params
  103 + })
  104 + },
  105 + // 2.2 客户跟进次数分析(按用户)
  106 + getFollowUpSummaryByUser: (params: any) => {
  107 + return request.get({
  108 + url: '/crm/statistics-customer/get-follow-up-summary-by-user',
  109 + params
  110 + })
  111 + },
  112 + // 3.1 获取客户跟进方式统计数
  113 + getFollowUpSummaryByType: (params: any) => {
  114 + return request.get({
  115 + url: '/crm/statistics-customer/get-follow-up-summary-by-type',
  116 + params
  117 + })
  118 + },
  119 + // 4.1 合同摘要信息(客户转化率页面)
  120 + getContractSummary: (params: any) => {
  121 + return request.get({
  122 + url: '/crm/statistics-customer/get-contract-summary',
  123 + params
  124 + })
  125 + },
  126 + // 5.1 获取客户公海分析(按日期)
  127 + getPoolSummaryByDate: (param: any) => {
  128 + return request.get({
  129 + url: '/crm/statistics-customer/get-pool-summary-by-date',
  130 + params: param
  131 + })
  132 + },
  133 + // 5.2 获取客户公海分析(按用户)
  134 + getPoolSummaryByUser: (param: any) => {
  135 + return request.get({
  136 + url: '/crm/statistics-customer/get-pool-summary-by-user',
  137 + params: param
  138 + })
  139 + },
  140 + // 6.1 获取客户成交周期(按日期)
  141 + getCustomerDealCycleByDate: (params: any) => {
  142 + return request.get({
  143 + url: '/crm/statistics-customer/get-customer-deal-cycle-by-date',
  144 + params
  145 + })
  146 + },
  147 + // 6.2 获取客户成交周期(按用户)
  148 + getCustomerDealCycleByUser: (params: any) => {
  149 + return request.get({
  150 + url: '/crm/statistics-customer/get-customer-deal-cycle-by-user',
  151 + params
  152 + })
  153 + },
  154 + // 6.2 获取客户成交周期(按用户)
  155 + getCustomerDealCycleByArea: (params: any) => {
  156 + return request.get({
  157 + url: '/crm/statistics-customer/get-customer-deal-cycle-by-area',
  158 + params
  159 + })
  160 + },
  161 + // 6.2 获取客户成交周期(按用户)
  162 + getCustomerDealCycleByProduct: (params: any) => {
  163 + return request.get({
  164 + url: '/crm/statistics-customer/get-customer-deal-cycle-by-product',
  165 + params
  166 + })
  167 + }
  168 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface CrmStatisticFunnelRespVO {
  4 + customerCount: number // 客户数
  5 + businessCount: number // 商机数
  6 + businessWinCount: number // 赢单数
  7 +}
  8 +
  9 +export interface CrmStatisticsBusinessSummaryByDateRespVO {
  10 + time: string // 时间
  11 + businessCreateCount: number // 商机数
  12 + totalPrice: number | string // 商机金额
  13 +}
  14 +
  15 +export interface CrmStatisticsBusinessInversionRateSummaryByDateRespVO {
  16 + time: string // 时间
  17 + businessCount: number // 商机数量
  18 + businessWinCount: number // 赢单商机数
  19 +}
  20 +
  21 +// 客户分析 API
  22 +export const StatisticFunnelApi = {
  23 + // 1. 获取销售漏斗统计数据
  24 + getFunnelSummary: (params: any) => {
  25 + return request.get({
  26 + url: '/crm/statistics-funnel/get-funnel-summary',
  27 + params
  28 + })
  29 + },
  30 + // 2. 获取商机结束状态统计
  31 + getBusinessSummaryByEndStatus: (params: any) => {
  32 + return request.get({
  33 + url: '/crm/statistics-funnel/get-business-summary-by-end-status',
  34 + params
  35 + })
  36 + },
  37 + // 3. 获取新增商机分析(按日期)
  38 + getBusinessSummaryByDate: (params: any) => {
  39 + return request.get({
  40 + url: '/crm/statistics-funnel/get-business-summary-by-date',
  41 + params
  42 + })
  43 + },
  44 + // 4. 获取商机转化率分析(按日期)
  45 + getBusinessInversionRateSummaryByDate: (params: any) => {
  46 + return request.get({
  47 + url: '/crm/statistics-funnel/get-business-inversion-rate-summary-by-date',
  48 + params
  49 + })
  50 + },
  51 + // 5. 获取商机列表(按日期)
  52 + getBusinessPageByDate: (params: any) => {
  53 + return request.get({
  54 + url: '/crm/statistics-funnel/get-business-page-by-date',
  55 + params
  56 + })
  57 + }
  58 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface StatisticsPerformanceRespVO {
  4 + time: string
  5 + currentMonthCount: number
  6 + lastMonthCount: number
  7 + lastYearCount: number
  8 +}
  9 +
  10 +// 排行 API
  11 +export const StatisticsPerformanceApi = {
  12 + // 员工获得合同金额统计
  13 + getContractPricePerformance: (params: any) => {
  14 + return request.get({
  15 + url: '/crm/statistics-performance/get-contract-price-performance',
  16 + params
  17 + })
  18 + },
  19 + // 员工获得回款统计
  20 + getReceivablePricePerformance: (params: any) => {
  21 + return request.get({
  22 + url: '/crm/statistics-performance/get-receivable-price-performance',
  23 + params
  24 + })
  25 + },
  26 + //员工获得签约合同数量统计
  27 + getContractCountPerformance: (params: any) => {
  28 + return request.get({
  29 + url: '/crm/statistics-performance/get-contract-count-performance',
  30 + params
  31 + })
  32 + }
  33 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface CrmStatisticCustomerBaseRespVO {
  4 + customerCount: number
  5 + dealCount: number
  6 + dealPortion: string | number
  7 +}
  8 +
  9 +export interface CrmStatisticCustomerIndustryRespVO extends CrmStatisticCustomerBaseRespVO {
  10 + industryId: number
  11 + industryPortion: string | number
  12 +}
  13 +
  14 +export interface CrmStatisticCustomerSourceRespVO extends CrmStatisticCustomerBaseRespVO {
  15 + source: number
  16 + sourcePortion: string | number
  17 +}
  18 +
  19 +export interface CrmStatisticCustomerLevelRespVO extends CrmStatisticCustomerBaseRespVO {
  20 + level: number
  21 + levelPortion: string | number
  22 +}
  23 +
  24 +export interface CrmStatisticCustomerAreaRespVO extends CrmStatisticCustomerBaseRespVO {
  25 + areaId: number
  26 + areaName: string
  27 + areaPortion: string | number
  28 +}
  29 +
  30 +// 客户分析 API
  31 +export const StatisticsPortraitApi = {
  32 + // 1. 获取客户行业统计数据
  33 + getCustomerIndustry: (params: any) => {
  34 + return request.get({
  35 + url: '/crm/statistics-portrait/get-customer-industry-summary',
  36 + params
  37 + })
  38 + },
  39 + // 2. 获取客户来源统计数据
  40 + getCustomerSource: (params: any) => {
  41 + return request.get({
  42 + url: '/crm/statistics-portrait/get-customer-source-summary',
  43 + params
  44 + })
  45 + },
  46 + // 3. 获取客户级别统计数据
  47 + getCustomerLevel: (params: any) => {
  48 + return request.get({
  49 + url: '/crm/statistics-portrait/get-customer-level-summary',
  50 + params
  51 + })
  52 + },
  53 + // 4. 获取客户地区统计数据
  54 + getCustomerArea: (params: any) => {
  55 + return request.get({
  56 + url: '/crm/statistics-portrait/get-customer-area-summary',
  57 + params
  58 + })
  59 + }
  60 +}
  1 +import request from '@/config/axios'
  2 +
  3 +export interface StatisticsRankRespVO {
  4 + count: number
  5 + nickname: string
  6 + deptName: string
  7 +}
  8 +
  9 +// 排行 API
  10 +export const StatisticsRankApi = {
  11 + // 获得合同排行榜
  12 + getContractPriceRank: (params: any) => {
  13 + return request.get({
  14 + url: '/crm/statistics-rank/get-contract-price-rank',
  15 + params
  16 + })
  17 + },
  18 + // 获得回款排行榜
  19 + getReceivablePriceRank: (params: any) => {
  20 + return request.get({
  21 + url: '/crm/statistics-rank/get-receivable-price-rank',
  22 + params
  23 + })
  24 + },
  25 + // 签约合同排行
  26 + getContractCountRank: (params: any) => {
  27 + return request.get({
  28 + url: '/crm/statistics-rank/get-contract-count-rank',
  29 + params
  30 + })
  31 + },
  32 + // 产品销量排行
  33 + getProductSalesRank: (params: any) => {
  34 + return request.get({
  35 + url: '/crm/statistics-rank/get-product-sales-rank',
  36 + params
  37 + })
  38 + },
  39 + // 新增客户数排行
  40 + getCustomerCountRank: (params: any) => {
  41 + return request.get({
  42 + url: '/crm/statistics-rank/get-customer-count-rank',
  43 + params
  44 + })
  45 + },
  46 + // 新增联系人数排行
  47 + getContactsCountRank: (params: any) => {
  48 + return request.get({
  49 + url: '/crm/statistics-rank/get-contacts-count-rank',
  50 + params
  51 + })
  52 + },
  53 + // 跟进次数排行
  54 + getFollowCountRank: (params: any) => {
  55 + return request.get({
  56 + url: '/crm/statistics-rank/get-follow-count-rank',
  57 + params
  58 + })
  59 + },
  60 + // 跟进客户数排行
  61 + getFollowCustomerCountRank: (params: any) => {
  62 + return request.get({
  63 + url: '/crm/statistics-rank/get-follow-customer-count-rank',
  64 + params
  65 + })
  66 + }
  67 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// ERP 结算账户 VO
  4 +export interface AccountVO {
  5 + id: number // 结算账户编号
  6 + no: string // 账户编码
  7 + remark: string // 备注
  8 + status: number // 开启状态
  9 + sort: number // 排序
  10 + defaultStatus: boolean // 是否默认
  11 + name: string // 账户名称
  12 +}
  13 +
  14 +// ERP 结算账户 API
  15 +export const AccountApi = {
  16 + // 查询结算账户分页
  17 + getAccountPage: async (params: any) => {
  18 + return await request.get({ url: `/erp/account/page`, params })
  19 + },
  20 +
  21 + // 查询结算账户精简列表
  22 + getAccountSimpleList: async () => {
  23 + return await request.get({ url: `/erp/account/simple-list` })
  24 + },
  25 +
  26 + // 查询结算账户详情
  27 + getAccount: async (id: number) => {
  28 + return await request.get({ url: `/erp/account/get?id=` + id })
  29 + },
  30 +
  31 + // 新增结算账户
  32 + createAccount: async (data: AccountVO) => {
  33 + return await request.post({ url: `/erp/account/create`, data })
  34 + },
  35 +
  36 + // 修改结算账户
  37 + updateAccount: async (data: AccountVO) => {
  38 + return await request.put({ url: `/erp/account/update`, data })
  39 + },
  40 +
  41 + // 修改结算账户默认状态
  42 + updateAccountDefaultStatus: async (id: number, defaultStatus: boolean) => {
  43 + return await request.put({
  44 + url: `/erp/account/update-default-status`,
  45 + params: {
  46 + id,
  47 + defaultStatus
  48 + }
  49 + })
  50 + },
  51 +
  52 + // 删除结算账户
  53 + deleteAccount: async (id: number) => {
  54 + return await request.delete({ url: `/erp/account/delete?id=` + id })
  55 + },
  56 +
  57 + // 导出结算账户 Excel
  58 + exportAccount: async (params: any) => {
  59 + return await request.download({ url: `/erp/account/export-excel`, params })
  60 + }
  61 +}
  1 +import request from '@/config/axios'
  2 +
  3 +// ERP 付款单 VO
  4 +export interface FinancePaymentVO {
  5 + id: number // 付款单编号
  6 + no: string // 付款单号
  7 + supplierId: number // 供应商编号
  8 + paymentTime: Date // 付款时间
  9 + totalPrice: number // 合计金额,单位:元
  10 + status: number // 状态
  11 + remark: string // 备注
  12 +}
  13 +
  14 +// ERP 付款单 API
  15 +export const FinancePaymentApi = {
  16 + // 查询付款单分页
  17 + getFinancePaymentPage: async (params: any) => {
  18 + return await request.get({ url: `/erp/finance-payment/page`, params })
  19 + },
  20 +
  21 + // 查询付款单详情
  22 + getFinancePayment: async (id: number) => {
  23 + return await request.get({ url: `/erp/finance-payment/get?id=` + id })
  24 + },
  25 +
  26 + // 新增付款单
  27 + createFinancePayment: async (data: FinancePaymentVO) => {
  28 + return await request.post({ url: `/erp/finance-payment/create`, data })
  29 + },
  30 +
  31 + // 修改付款单
  32 + updateFinancePayment: async (data: FinancePaymentVO) => {
  33 + return await request.put({ url: `/erp/finance-payment/update`, data })
  34 + },
  35 +
  36 + // 更新付款单的状态
  37 + updateFinancePaymentStatus: async (id: number, status: number) => {
  38 + return await request.put({
  39 + url: `/erp/finance-payment/update-status`,
  40 + params: {
  41 + id,
  42 + status
  43 + }
  44 + })
  45 + },
  46 +
  47 + // 删除付款单
  48 + deleteFinancePayment: async (ids: number[]) => {
  49 + return await request.delete({
  50 + url: `/erp/finance-payment/delete`,
  51 + params: {
  52 + ids: ids.join(',')
  53 + }
  54 + })
  55 + },
  56 +
  57 + // 导出付款单 Excel
  58 + exportFinancePayment: async (params: any) => {
  59 + return await request.download({ url: `/erp/finance-payment/export-excel`, params })
  60 + }
  61 +}