li.shaoyi 3 년 전
부모
커밋
92c4920ec9
76개의 변경된 파일1035개의 추가작업 그리고 666개의 파일을 삭제
  1. 5 11
      src/business/auth/index.ts
  2. 1 0
      src/components/base/modal/index.ts
  3. 3 1
      src/constants/market.ts
  4. 1 0
      src/constants/order.ts
  5. 43 10
      src/filters/index.ts
  6. 74 14
      src/hooks/component/index.ts
  7. 3 0
      src/hooks/datatable/index.ts
  8. 1 1
      src/hooks/menu/index.ts
  9. 58 0
      src/hooks/navigation/index.ts
  10. 0 47
      src/hooks/scroll-visibility/index.ts
  11. 0 1
      src/packages/mobile/assets/themes/base/reset.less
  12. 76 0
      src/packages/mobile/components/base/pull-refresh/index.vue
  13. 1 1
      src/packages/mobile/components/base/tabbar/index.less
  14. 1 1
      src/packages/mobile/components/base/tabbar/index.vue
  15. 1 0
      src/packages/mobile/components/layouts/footer/index.less
  16. 12 0
      src/packages/mobile/components/layouts/footer/index.vue
  17. 4 0
      src/packages/mobile/components/layouts/index.ts
  18. 8 0
      src/packages/mobile/components/layouts/navbar/index.less
  19. 1 2
      src/packages/mobile/components/layouts/navbar/index.vue
  20. 8 8
      src/packages/mobile/components/layouts/page/index.less
  21. 15 5
      src/packages/mobile/components/layouts/page/index.vue
  22. 19 0
      src/packages/mobile/components/layouts/scroll-view/index.less
  23. 71 20
      src/packages/mobile/components/layouts/scroll-view/index.vue
  24. 11 0
      src/packages/mobile/components/layouts/view/index.less
  25. 38 0
      src/packages/mobile/components/layouts/view/index.vue
  26. 21 21
      src/packages/mobile/router/animateRouter.ts
  27. 3 3
      src/packages/mobile/router/index.ts
  28. 0 0
      src/packages/mobile/views/auth/login/index.less
  29. 48 0
      src/packages/mobile/views/auth/login/index.vue
  30. 0 0
      src/packages/mobile/views/auth/register/index.vue
  31. 21 23
      src/packages/mobile/views/home/components/main/index.vue
  32. 6 4
      src/packages/mobile/views/home/components/market/index.vue
  33. 6 4
      src/packages/mobile/views/home/components/mine/index.vue
  34. 7 5
      src/packages/mobile/views/home/components/order/index.vue
  35. 1 1
      src/packages/mobile/views/home/index.less
  36. 1 1
      src/packages/mobile/views/home/index.vue
  37. 19 14
      src/packages/mobile/views/order/detail/index.vue
  38. 0 67
      src/packages/mobile/views/order/index/index.vue
  39. 0 0
      src/packages/mobile/views/order/main/index.less
  40. 48 0
      src/packages/mobile/views/order/main/index.vue
  41. 0 50
      src/packages/mobile/views/sign/login/index.vue
  42. 42 42
      src/packages/pc/assets/themes/default/default.less
  43. 3 3
      src/packages/pc/components/layouts/header/index.vue
  44. 2 2
      src/packages/pc/components/layouts/main/index.vue
  45. 2 2
      src/packages/pc/components/layouts/sidebar/index.vue
  46. 2 2
      src/packages/pc/components/layouts/sidemenu/index.vue
  47. 2 2
      src/packages/pc/components/modules/auth-component/index.vue
  48. 2 2
      src/packages/pc/components/modules/auth-operation/index.vue
  49. 14 14
      src/packages/pc/router/historyRouter.ts
  50. 1 1
      src/packages/pc/router/index.ts
  51. 0 0
      src/packages/pc/views/auth/components/layout/index.less
  52. 0 0
      src/packages/pc/views/auth/components/layout/index.vue
  53. 0 0
      src/packages/pc/views/auth/login/index.less
  54. 5 5
      src/packages/pc/views/auth/login/index.vue
  55. 2 2
      src/packages/pc/views/system/role/components/auth/index.vue
  56. 2 2
      src/packages/pc/views/trade/buy/components/details/index.vue
  57. 10 10
      src/services/api/account/index.ts
  58. 10 10
      src/services/api/bank/index.ts
  59. 16 16
      src/services/api/common/index.ts
  60. 12 12
      src/services/api/customs/index.ts
  61. 4 4
      src/services/api/favorite/index.ts
  62. 7 7
      src/services/api/goods/index.ts
  63. 10 10
      src/services/api/performance/index.ts
  64. 3 3
      src/services/api/quote/index.ts
  65. 18 18
      src/services/api/trade/index.ts
  66. 9 9
      src/services/api/user/index.ts
  67. 4 4
      src/services/api/warehouse/index.ts
  68. 119 83
      src/services/http/index.ts
  69. 19 6
      src/services/http/interface.ts
  70. 18 24
      src/services/index.ts
  71. 3 3
      src/services/socket/trade/index.ts
  72. 1 1
      src/services/socket/trade/interface.ts
  73. 20 25
      src/stores/@next.ts
  74. 1 1
      src/stores/modules/login.ts
  75. 35 26
      src/types/ermcp/account.d.ts
  76. 1 0
      src/types/ermcp/trade.d.ts

+ 5 - 11
src/business/sign/index.ts → src/business/auth/index.ts

@@ -5,7 +5,7 @@ import { useLoginStore } from '@/stores'
 import { initBaseData } from '@/business/common'
 import eventBus from '@/services/bus'
 
-export function useSign() {
+export function useAuth() {
     const { userLogin } = useLoginStore();
     const loading = ref(false);
     const user = reactive<Proto.LoginReq>({
@@ -18,13 +18,8 @@ export function useSign() {
         DeviceID: ''
     })
 
-    // 用户注册
-    const signUp = () => {
-        console.log('用户注册')
-    }
-
     // 用户登录
-    const signIn = () => {
+    const login = () => {
         loading.value = true
         return new Promise((resolve, reject) => {
             userLogin(user).then((res) => {
@@ -42,15 +37,14 @@ export function useSign() {
     }
 
     // 用户登出
-    const signOut = () => {
+    const logout = () => {
         eventBus.$emit('LogoutNotify')
     }
 
     return {
         loading,
         user,
-        signUp,
-        signIn,
-        signOut,
+        login,
+        logout,
     }
 }

+ 1 - 0
src/components/base/modal/index.ts

@@ -16,6 +16,7 @@ export function useModal(isShow: boolean, delay: number) {
 
     // 动画切换
     const transition = (isShow: boolean, callback?: () => void) => {
+        if (isShow) visible.value = true
         window.setTimeout(() => {
             transitionClass.value = isShow ? 'is-show' : 'is-hide';
             // 阻止鼠标事件,防止动画过程中触发事件

+ 3 - 1
src/constants/market.ts

@@ -2,6 +2,8 @@
  * 交易市场
  */
 export enum Market {
-    /** 广钻市场 */
+    /** 广钻 */
     GZ = 67201,
+    /** 铁合金 */
+    THJ = 64201,
 }

+ 1 - 0
src/constants/order.ts

@@ -2,6 +2,7 @@ import { useEnumStore } from '@/stores'
 import { usePerformanceStore } from '@/stores'
 
 const { getEnumTypeList, getEnumTypeName } = useEnumStore()
+
 /**
  * 买卖方向
  */

+ 43 - 10
src/filters/index.ts

@@ -1,6 +1,21 @@
+import CryptoJS from 'crypto-js'
+import service from '@/services'
 import moment from 'moment'
 
 /**
+ * 获取图片地址
+ * @param fileUrl 
+ */
+export function getImageUrl(fileUrl: string) {
+    if (fileUrl) {
+        const { openApiUrl } = service.config
+        return openApiUrl + fileUrl.replace('./', '/')
+    }
+    // 返回默认图片
+    return ''
+}
+
+/**
  * 处理价格颜色的显示
  */
 export function handlePriceColor(curValue: number, preValue: number) {
@@ -59,17 +74,12 @@ export function formatDecimal(value: number | string, decimal = 2, round = true)
         }
         let num = val.toString()
         const index = num.indexOf('.')
-        if (index < 0) {
-            // 小数位自动补零
-            if (decimal > 0) {
-                const count = num.length
-                num += '.'
-                while (num.length <= count + decimal) {
-                    num += '0'
-                }
-            }
+        if (index !== -1) {
+            num = num.substring(0, decimal + index + 1)
+        } else {
+            num = num.substring(0)
         }
-        return num.substring(0, decimal + index + 1)
+        return parseFloat(num).toFixed(decimal)
     }
 }
 
@@ -93,4 +103,27 @@ export function formatAmount(value: number, decimal = 2) {
  */
 export function formatDate(date: string, format = 'YYYY-MM-DD HH:mm:ss') {
     return moment(date).format(format)
+}
+
+/**
+ * Des密钥
+ * 手机发送验证码时加密方法
+ * @param mobile
+ */
+export function encryptDesMobile(mobile: string) {
+    const hexKey = CryptoJS.enc.Utf8.parse('Ub$kl^P3')
+    const hexData = CryptoJS.enc.Utf8.parse(mobile)
+    const desData = CryptoJS.DES.encrypt(hexData, hexKey, { iv: hexKey })
+    const encrypted = CryptoJS.enc.Base64.stringify(desData.ciphertext)
+    return encrypted
+}
+
+/**
+ * 获取加密后的手机号码
+ * @param mobile 手机号码
+ * @returns 加密后的手机号码
+ */
+export function getEncryptMobile(mobile: string) {
+    const encryptMobile = encryptDesMobile(mobile)
+    return encryptMobile.replace(new RegExp('\\+', 'g'), '*').replace(new RegExp('\\/', 'g'), '-').replace(new RegExp('\\=', 'g'), '.')
 }

+ 74 - 14
src/hooks/component/index.ts

@@ -1,24 +1,39 @@
-import { ref } from 'vue'
+import { ref, Ref, onUnmounted } from 'vue'
+import { onBeforeRouteLeave } from 'vue-router'
+import { v4 } from 'uuid'
+
+// 缓存已打开的组件实例
+const componentInstanceMap = new Map<string, Ref>()
 
 /**
  * @param callback 组件关闭时的回调
  * @returns 
  */
 export function useComponent(callback?: (componentName?: string) => void) {
-    // 组件名
-    const componentId = ref<string>();
+    const uuid = v4()
+    const components = new Set<string>() // 已打开的组件列表
+    const componentId = ref<string>() // 当前显示的组件
+    const componentRef = ref() // 组件实例
+
+    // 添加到组件实例
+    componentInstanceMap.set(uuid, componentRef)
+
+    /**
+     * 是否存在组件
+     * @returns 
+     */
+    const hasComponent = () => {
+        return components.size > 0
+    }
 
     /**
      * 打开组件
      * @param componentName 
      */
     const openComponent = (componentName: string) => {
-        if (componentName) {
-            console.log('打开组件:' + componentName.toString());
-            componentId.value = componentName;
-        } else {
-            console.error('无效的组件名');
-        }
+        console.log('打开组件:' + componentName)
+        components.add(componentName)
+        componentId.value = componentName
     }
 
     /**
@@ -27,18 +42,63 @@ export function useComponent(callback?: (componentName?: string) => void) {
      */
     const closeComponent = (isCallback?: boolean) => {
         const componentName = componentId.value
-        componentId.value = undefined;
-        console.log('关闭组件:' + componentName);
+        if (componentName) {
+            console.log('关闭组件:' + componentName)
+            components.delete(componentName)
+            componentId.value = [...components.values()].pop()
 
-        // 是否刷新数据
-        if (isCallback && callback) {
-            callback(componentName);
+            // 是否刷新数据
+            if (isCallback && callback) {
+                callback(componentName)
+            }
         }
     }
 
+    /**
+     * 组件关闭守卫
+     * @returns 
+     */
+    const closeComponentEach = () => {
+        if (hasComponent()) {
+            const mapValues = [...componentInstanceMap.values()]
+            // 倒序关闭已打开的组件
+            for (let i = mapValues.length - 1; i >= 0; i--) {
+                const componentInstance = mapValues[i].value
+                if (componentInstance) {
+                    const { closed } = componentInstance ?? {}
+                    if (closed instanceof Function) {
+                        closed()
+                        return false
+                    }
+                }
+            }
+            closeComponent()
+            return false
+        }
+        return true
+    }
+
+    /**
+     * 路由守卫,离开页面前关闭组件
+     */
+    onBeforeRouteLeave((to, from, next) => {
+        if (closeComponentEach()) {
+            next()
+        } else {
+            next(false)
+        }
+    })
+
+    onUnmounted(() => {
+        componentInstanceMap.delete(uuid)
+    })
+
     return {
         componentId,
+        componentRef,
+        hasComponent,
         openComponent,
         closeComponent,
+        closeComponentEach,
     }
 }

+ 3 - 0
src/hooks/datatable/index.ts

@@ -10,6 +10,8 @@ export function useDataTable<T>(options: DataTableOptions = {}) {
     const pageSize = shallowRef(options.pageSize ?? 20)
     // 当前页码
     const pageIndex = shallowRef(options.pageIndex ?? 1)
+    // 总页数
+    const pageCount = computed(() => Math.ceil(total.value / pageSize.value) || 1)
     // 过滤筛选值
     const filters = shallowRef<FilterValue<T>[]>([])
     // 过滤选项
@@ -130,6 +132,7 @@ export function useDataTable<T>(options: DataTableOptions = {}) {
         total,
         pageIndex,
         pageSize,
+        pageCount,
         filterMethod,
         getQueryParam,
         ...toRefs(filterOptons),

+ 1 - 1
src/hooks/auth/index.ts → src/hooks/menu/index.ts

@@ -3,7 +3,7 @@ import { useRoute, useRouter } from 'vue-router'
 import { useMenuStore } from '@/stores'
 import { AuthType } from '@/constants/menu'
 
-export function useAuth(authCode?: string) {
+export function useMenu(authCode?: string) {
     const { userMenus } = useMenuStore()
     const route = useRoute()
     const router = useRouter()

+ 58 - 0
src/hooks/navigation/index.ts

@@ -0,0 +1,58 @@
+import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router'
+import animateRouter from '@mobile/router/animateRouter'
+
+export function useNavigation() {
+    const route = useRoute()
+    const router = useRouter()
+
+    // 缓存全局Url参数
+    const setGlobalUrlParams = (params: unknown) => {
+        sessionStorage.setItem('globalUrlParams', JSON.stringify(params))
+    }
+
+    // 获取全局Url参数(只能获取一次)
+    const getGlobalUrlParams = () => {
+        const params = sessionStorage.getItem('globalUrlParams')
+        if (params) {
+            sessionStorage.removeItem('globalUrlParams')
+            return JSON.parse(params)
+        } else {
+            return {}
+        }
+    }
+
+    // 返回指定页面
+    const backTo = <T extends object>(to: string, params?: T) => {
+        const { state } = animateRouter
+        const total = state.history.length - 1
+        const index = state.history.findIndex(((e) => e.name === to))
+
+        if (index > -1) {
+            const delta = total - index
+            if (delta > 0) {
+                setGlobalUrlParams(params ?? {})
+                router.go(-delta)
+            }
+        }
+    }
+
+    // 导航守卫
+    const beforeRouteLeave = (callback: () => boolean) => {
+        onBeforeRouteLeave((to, from, next) => {
+            if (callback()) {
+                next()
+            } else {
+                next(false)
+            }
+        })
+    }
+
+    return {
+        route,
+        router,
+        setGlobalUrlParams,
+        getGlobalUrlParams,
+        backTo,
+        beforeRouteLeave,
+    }
+}

+ 0 - 47
src/hooks/scroll-visibility/index.ts

@@ -1,47 +0,0 @@
-import { ref, reactive, watch } from 'vue'
-
-/**
- * 滚动显示隐藏元素
- * @param defaultOpacity 默认透明度
- * @returns 
- */
-export function useScrollVisibility(defaultOpacity = 1) {
-    // 滚动条高度
-    const scrollTop = ref(0);
-    // 目标元素
-    const visibilityElement = ref<HTMLElement>();
-    // 滚动元素样式
-    const scrollElementStyles = reactive({
-        paddingTop: '0px',
-    })
-
-    // 绑定元素
-    const bindVisibilityElement = (el: HTMLElement) => {
-        const { clientHeight, style } = el;
-        visibilityElement.value = el;
-        scrollElementStyles.paddingTop = (defaultOpacity ? clientHeight : 0) + 'px';
-        style.setProperty('opacity', defaultOpacity.toString());
-    }
-
-    // 监听滚动条位置
-    watch(scrollTop, (val) => {
-        if (visibilityElement.value) {
-            const { clientHeight, style } = visibilityElement.value;
-            const alpha = (defaultOpacity ? (clientHeight * 2 - val) : (val - clientHeight)) / clientHeight; // 根据默认透明度判断渐变方向
-
-            if (alpha > 1) {
-                style.setProperty('opacity', '1');
-            } else if (alpha < 0) {
-                style.setProperty('opacity', '0');
-            } else {
-                style.setProperty('opacity', alpha.toString());
-            }
-        }
-    })
-
-    return {
-        scrollTop,
-        scrollElementStyles,
-        bindVisibilityElement,
-    }
-}

+ 0 - 1
src/packages/mobile/assets/themes/base/reset.less

@@ -24,7 +24,6 @@ html {
 
 body {
     height                    : inherit;
-    line-height               : 1;
     font-size                 : .28rem;
     background-color          : #666;
     margin                    : auto !important;

+ 76 - 0
src/packages/mobile/components/base/pull-refresh/index.vue

@@ -0,0 +1,76 @@
+<template>
+    <PullRefresh v-model="refreshing" @refresh="onRefresh">
+        <slot name="header"></slot>
+        <List v-model:loading="showLoading" :finished="finished" :finished-text="finishedText" @load="onLoad">
+            <template v-for="(item, index) in tableSource" :key="index">
+                <slot :item="item" :index="index"></slot>
+            </template>
+        </List>
+        <slot name="footer"></slot>
+    </PullRefresh>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, computed, PropType } from 'vue'
+import { List, PullRefresh } from 'vant'
+
+const props = defineProps({
+    loading: {
+        type: Boolean,
+    },
+    total: {
+        type: Number,
+        default: 0,
+    },
+    dataList: {
+        // eslint-disable-next-line
+        type: Array as PropType<any>,
+        required: true
+    },
+    finishedText: {
+        type: String,
+        default: '没有更多了',
+    }
+})
+
+const emit = defineEmits(['update:loading', 'update:dataList', 'refresh'])
+const refreshing = shallowRef(false) // 是否处于加载中状态
+const finished = shallowRef(false) // 是否已加载完成所有数据
+
+const showLoading = computed({
+    get: () => props.loading,
+    set: (val) => emit('update:loading', val)
+})
+
+const tableSource = computed({
+    get: () => props.dataList,
+    set: (val) => {
+        emit('update:dataList', val)
+    }
+})
+
+// 上拉加载
+const onLoad = () => {
+    const resolve = (data?: unknown[]) => {
+        const list = tableSource.value
+        if (refreshing.value) {
+            list.length = 0
+            refreshing.value = false
+        }
+        if (data) {
+            list.push(...data)
+        }
+        if (list.length >= props.total) {
+            finished.value = true
+        }
+        tableSource.value = list
+    }
+    emit('refresh', resolve)
+}
+
+// 下拉刷新
+const onRefresh = () => {
+    finished.value = false
+    onLoad()
+}
+</script>

+ 1 - 1
src/packages/mobile/components/base/tabbar/index.less

@@ -2,7 +2,7 @@
     height          : 1rem;
     background-color: #fff;
 
-    &__warpper {
+    &__wrapper {
         bottom    : 0;
         display   : flex;
         width     : 100%;

+ 1 - 1
src/packages/mobile/components/base/tabbar/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="app-tabbar">
-    <div class="app-tabbar__warpper" :style="styles">
+    <div class="app-tabbar__wrapper" :style="styles">
       <template v-for="(item, index) in dataList" :key="index">
         <div class="app-tabbar__item" @click="onChange(index)">
           <slot :item="item" :index="index">

+ 1 - 0
src/packages/mobile/components/layouts/footer/index.less

@@ -0,0 +1 @@
+.app-footer {}

+ 12 - 0
src/packages/mobile/components/layouts/footer/index.vue

@@ -0,0 +1,12 @@
+<template>
+    <div class="app-footer">
+        <slot></slot>
+    </div>
+</template>
+
+<script lang="ts" setup>
+</script>
+
+<style lang="less">
+@import './index.less';
+</style>

+ 4 - 0
src/packages/mobile/components/layouts/index.ts

@@ -1,11 +1,15 @@
 import { App } from 'vue'
 import AppPage from './page/index.vue'
+import AppView from './view/index.vue'
 import AppScrollView from './scroll-view/index.vue'
 import AppStatusbar from './statusbar/index.vue'
 import AppNavbar from './navbar/index.vue'
+import AppFooter from './footer/index.vue'
 
 const components = {
     AppPage,
+    AppView,
+    AppFooter,
     AppScrollView,
     AppStatusbar,
     AppNavbar,

+ 8 - 0
src/packages/mobile/components/layouts/navbar/index.less

@@ -1,4 +1,6 @@
 .app-navbar {
+    z-index: 1;
+
     &__wrapper {
         background: var(--navbar-background);
         color     : var(--navbar-color);
@@ -51,4 +53,10 @@
             }
         }
     }
+
+    &__footer {
+        &:empty {
+            display: none;
+        }
+    }
 }

+ 1 - 2
src/packages/mobile/components/layouts/navbar/index.vue

@@ -25,7 +25,7 @@
           </div>
         </div>
       </div>
-      <div class="app-navbar__footer" v-if="$slots.footer">
+      <div class="app-navbar__footer">
         <slot name="footer"></slot>
       </div>
     </app-statusbar>
@@ -58,7 +58,6 @@ const { state } = client;
 
 const styles = computed(() => ({
   position: props.fixed ? 'fixed' : 'static',
-  zIndex: props.fixed ? '1' : 'auto',
   width: state.clientWidth + 'px',
 }))
 

+ 8 - 8
src/packages/mobile/components/layouts/page/index.less

@@ -1,17 +1,17 @@
-.slide-left-enter-from {
+.route-in-enter-from {
     z-index  : 1;
     transform: translate3d(100%, 0, 0);
 }
 
-.slide-right-enter-from {
+.route-out-enter-from {
     z-index  : 1;
     transform: translate3d(-100%, 0, 0);
 }
 
-.slide-left-enter-active,
-.slide-left-leave-active,
-.slide-right-enter-active,
-.slide-right-leave-active {
+.route-in-enter-active,
+.route-in-leave-active,
+.route-out-enter-active,
+.route-out-leave-active {
     pointer-events  : none;
     position        : absolute;
     will-change     : transform;
@@ -19,12 +19,12 @@
     background-color: #fff;
 }
 
-.slide-right-leave-active {
+.route-out-leave-active {
     transition-delay: 35ms;
     transform       : translate3d(100%, 0, 0);
 }
 
-.slide-left-leave-active {
+.route-in-leave-active {
     transition-delay: 35ms;
     transform       : translate3d(-100%, 0, 0);
 }

+ 15 - 5
src/packages/mobile/components/layouts/page/index.vue

@@ -1,25 +1,35 @@
 <template>
   <router-view class="app-page" v-slot="{ Component, route }">
-    <transition :name="state.transitionName">
+    <transition :name="state.transitionName" @leave="onLeave" @after-enter="onAfterEnter">
       <keep-alive :exclude="state.excludeViews">
-        <component :is="handleComponent(Component, route)" :key="$route.fullPath" />
+        <component :is="handleComponent(Component, route)" :key="$route.fullPath" :animationstart="animationstart" />
       </keep-alive>
     </transition>
   </router-view>
 </template>
 
 <script lang="ts" setup>
+import { shallowRef } from 'vue'
 import { RouteRecordNormalized, RouteRecordName } from 'vue-router'
 import animateRouter from '@mobile/router/animateRouter'
 
-const { state } = animateRouter;
+const { state } = animateRouter
+const animationstart = shallowRef(false)
 
 // 手动给组件添加 name 属性,处理缓存 exclude 无效的问题
 const handleComponent = (component: Record<'type', { name: RouteRecordName | undefined }>, route: RouteRecordNormalized) => {
   if (component) {
-    component.type.name = route.name;
+    component.type.name = route.name
   }
-  return component;
+  return component
+}
+
+const onLeave = () => {
+  animationstart.value = true
+}
+
+const onAfterEnter = () => {
+  animationstart.value = false
 }
 </script>
 

+ 19 - 0
src/packages/mobile/components/layouts/scroll-view/index.less

@@ -0,0 +1,19 @@
+.app-scroll-view {
+    height    : 100%;
+    overflow-y: auto;
+
+    &__header {
+        position: fixed;
+        top     : 0;
+        z-index : 1;
+
+        &:empty {
+            display: none;
+        }
+
+        &.after {
+            opacity: 0;
+            z-index: -1;
+        }
+    }
+}

+ 71 - 20
src/packages/mobile/components/layouts/scroll-view/index.vue

@@ -1,13 +1,17 @@
 <template>
-  <div class="app-scroll-view" ref="scrollElement">
+  <div ref="scrollRef" class="app-scroll-view">
+    <div ref="afterHeaderRef" class="app-scroll-view__header after">
+      <slot name="afterHeader"></slot>
+    </div>
+    <div ref="beforeHeaderRef" class="app-scroll-view__header before">
+      <slot name="beforeHeader"></slot>
+    </div>
     <slot></slot>
   </div>
 </template>
 
 <script lang="ts" setup>
-import { ref, onActivated, onDeactivated, watch } from 'vue'
-
-const emit = defineEmits(['update:scrollTop', 'scroll']);
+import { ref, onMounted, onActivated, onDeactivated, watch } from 'vue'
 
 const props = defineProps({
   // 滚动元素名称(用于不同组件缓存滚动条位置)
@@ -19,44 +23,91 @@ const props = defineProps({
   scrollTop: {
     type: Number,
     default: 0,
-  }
+  },
 })
 
-const scrollElement = ref<HTMLDivElement>();
-const scrollMap = new Map<string, number>();
+const emit = defineEmits(['update:scrollTop', 'scroll'])
+const scrollRef = ref<HTMLDivElement>()
+const beforeHeaderRef = ref<HTMLDivElement>() // 前标题栏
+const afterHeaderRef = ref<HTMLDivElement>() // 后标题栏
+const scrollMap = new Map<string, number>()
+
+// 设置透明样式
+const setOpacity = (style: CSSStyleDeclaration, value: number) => {
+  if (value > 1) {
+    style.setProperty('opacity', '1')
+  } else if (value < 0) {
+    style.setProperty('opacity', '0')
+    style.setProperty('z-index', '-1')
+  } else {
+    style.setProperty('opacity', value.toString())
+    style.setProperty('z-index', '1')
+  }
+}
 
 // 监听滚动条位置
 const onScroll = (e: Event) => {
-  const el = e.target as HTMLDivElement;
-  scrollMap.set(props.scrollName, el.scrollTop);
-  emit('update:scrollTop', el.scrollTop);
+  const el = e.target as HTMLDivElement
+  const beforeHeaderEl = beforeHeaderRef.value
+  const afterHeaderEl = afterHeaderRef.value
+  scrollMap.set(props.scrollName, el.scrollTop)
+
+  // 滚动隐藏标题栏
+  if (beforeHeaderEl) {
+    const { clientHeight, style } = beforeHeaderEl
+    const alpha = (clientHeight * 2 - el.scrollTop) / clientHeight
+    setOpacity(style, alpha)
+  }
+  // 滚动显示标题栏
+  if (afterHeaderEl) {
+    const { clientHeight, style } = afterHeaderEl
+    const alpha = (el.scrollTop - clientHeight) / clientHeight
+    setOpacity(style, alpha)
+  }
+
+  emit('update:scrollTop', el.scrollTop)
   emit('scroll', el)
 }
 
 // 设置滚动条位置
 const setScrollTop = (callback?: (el: HTMLDivElement) => void) => {
-  const el = scrollElement.value;
+  const el = scrollRef.value
   if (el) {
-    el.style.setProperty('opacity', '0');
-    el.scrollTop = scrollMap.get(props.scrollName) ?? 0;
+    el.style.setProperty('opacity', '0')
+    el.scrollTop = scrollMap.get(props.scrollName) ?? 0
 
     window.setTimeout(() => {
-      el.style.setProperty('opacity', '1');
-      callback && callback(el);
+      el.style.setProperty('opacity', '1')
+      callback && callback(el)
     }, 0)
   }
 }
 
+onMounted(() => {
+  window.setTimeout(() => {
+    const scrollEl = scrollRef.value
+    const beforeHeaderEl = beforeHeaderRef.value
+
+    if (scrollEl && beforeHeaderEl) {
+      scrollEl.style.setProperty('padding-top', beforeHeaderEl.clientHeight + 'px')
+    }
+  }, 0)
+})
+
 onActivated(() => {
   setScrollTop((el) => {
-    el.addEventListener('scroll', onScroll); // 监听滚动条事件
+    el?.addEventListener('scroll', onScroll) // 监听滚动条事件
   })
 })
 
 onDeactivated(() => {
-  const el = scrollElement.value;
-  el?.removeEventListener('scroll', onScroll); // 移除滚动条事件
+  const el = scrollRef.value
+  el?.removeEventListener('scroll', onScroll) // 移除滚动条事件
 })
 
-watch(() => props.scrollName, () => setScrollTop());
-</script>
+watch(() => props.scrollName, () => setScrollTop())
+</script>
+
+<style lang="less" scoped>
+@import './index.less';
+</style>

+ 11 - 0
src/packages/mobile/components/layouts/view/index.less

@@ -0,0 +1,11 @@
+.app-view {
+    display                   : flex;
+    flex-direction            : column;
+    height                    : 100%;
+    -webkit-overflow-scrolling: touch;
+
+    &__wrapper {
+        flex      : 1;
+        overflow-y: auto;
+    }
+}

+ 38 - 0
src/packages/mobile/components/layouts/view/index.vue

@@ -0,0 +1,38 @@
+<template>
+    <div class="app-view">
+        <slot name="header"></slot>
+        <app-scroll-view class="app-view__wrapper">
+            <slot></slot>
+        </app-scroll-view>
+        <slot name="footer"></slot>
+    </div>
+</template>
+
+<script lang="ts" setup>
+import { watch } from 'vue'
+
+const props = defineProps({
+    // 是否为过渡动画状态
+    animationstart: {
+        type: Boolean,
+        default: false
+    },
+    // 过渡动画是否已结束,用于防止动画过程中渲染数据导致页面切换卡顿
+    animationend: {
+        type: Boolean,
+        default: true
+    },
+})
+
+const emit = defineEmits(['update:animationend'])
+
+watch(() => props.animationstart, (status) => {
+    if (!status) {
+        emit('update:animationend', true)
+    }
+})
+</script>
+
+<style lang="less" scoped>
+@import './index.less';
+</style>

+ 21 - 21
src/packages/mobile/router/animateRouter.ts

@@ -2,15 +2,15 @@ import { ref, toRefs, readonly } from 'vue'
 import { createRouter, RouterOptions, RouteRecordRaw, RouteLocationNormalized } from 'vue-router'
 
 interface HistoryState {
-    historyStacks: RouteLocationNormalized[]; // 已访问的路由列表
+    history: RouteLocationNormalized[]; // 已访问的路由列表
     excludeViews: string[]; // 不缓存的页面
     actionName: '' | 'push' | 'replace' | 'forward' | 'back'; // 当前路由动作
-    transitionName: '' | 'slide-right' | 'slide-left'; // 前进后退动画
+    transitionName: '' | 'route-out' | 'route-in'; // 前进后退动画
 }
 
 export default new (class {
     private _state = ref<HistoryState>({
-        historyStacks: [],
+        history: [],
         excludeViews: [],
         actionName: '',
         transitionName: '',
@@ -89,25 +89,25 @@ export default new (class {
      * @param route 
      */
     private addHistory = (route: RouteLocationNormalized) => {
-        const { historyStacks, excludeViews, actionName, transitionName } = toRefs(this._state.value);
+        const { history, excludeViews, actionName, transitionName } = toRefs(this._state.value);
 
         // 如果是替换动作,必定是前进
         if (actionName.value === 'replace') {
-            const lastIndex = historyStacks.value.length - 1;
-            const lastView = historyStacks.value[lastIndex];
+            const lastIndex = history.value.length - 1;
+            const lastView = history.value[lastIndex];
 
             if (lastView) {
                 excludeViews.value.push(lastView.name as string);
-                historyStacks.value[lastIndex] = route; // 更新最后一条记录
+                history.value[lastIndex] = route; // 更新最后一条记录
             } else {
-                historyStacks.value.push(route);
+                history.value.push(route);
             }
-            transitionName.value = 'slide-left'; // 前进动画
+            transitionName.value = 'route-in'; // 前进动画
         } else {
             // 倒序查找路由所在的位置
             const index = (() => {
-                for (let i = historyStacks.value.length - 1; i >= 0; i--) {
-                    if (historyStacks.value[i].fullPath == route.fullPath) {
+                for (let i = history.value.length - 1; i >= 0; i--) {
+                    if (history.value[i].fullPath == route.fullPath) {
                         return i;
                     }
                 }
@@ -116,24 +116,24 @@ export default new (class {
 
             if (index > -1) {
                 if (actionName.value === 'push') {
-                    historyStacks.value.push(route);
-                    transitionName.value = 'slide-left'; //前进动画
+                    history.value.push(route);
+                    transitionName.value = 'route-in'; //前进动画
                 } else {
-                    if (historyStacks.value.length > 1) {
+                    if (history.value.length > 1) {
                         const i = index + 1;
-                        const n = historyStacks.value.length - i;
+                        const n = history.value.length - i;
 
-                        excludeViews.value = historyStacks.value.map((e) => e.name).slice(-n) as string[]; // 返回数组最后位置开始的n个元素
-                        historyStacks.value.splice(i, n); // 从i位置开始删除后面所有元素(包括i)
+                        excludeViews.value = history.value.map((e) => e.name).slice(-n) as string[]; // 返回数组最后位置开始的n个元素
+                        history.value.splice(i, n); // 从i位置开始删除后面所有元素(包括i)
                     }
-                    transitionName.value = 'slide-right'; //后退动画
+                    transitionName.value = 'route-out'; //后退动画
                 }
             } else {
                 // 忽略重定向的页面
                 if (!route.redirectedFrom) {
-                    historyStacks.value.push(route);
-                    if (historyStacks.value.length > 1) {
-                        transitionName.value = 'slide-left'; // 前进动画
+                    history.value.push(route);
+                    if (history.value.length > 1) {
+                        transitionName.value = 'route-in'; // 前进动画
                     }
                 }
             }

+ 3 - 3
src/packages/mobile/router/index.ts

@@ -38,7 +38,7 @@ const routes: Array<RouteRecordRaw> = [
       {
         path: '',
         name: 'login',
-        component: () => import('../views/sign/login/index.vue'),
+        component: () => import('../views/auth/login/index.vue'),
       }
     ]
   },
@@ -49,7 +49,7 @@ const routes: Array<RouteRecordRaw> = [
       {
         path: '',
         name: 'order',
-        component: () => import('../views/order/index/index.vue'),
+        component: () => import('../views/order/main/index.vue'),
       },
       {
         path: 'detail',
@@ -62,7 +62,7 @@ const routes: Array<RouteRecordRaw> = [
 
 const router = animateRouter.create({
   history: createWebHashHistory(),
-  routes
+  routes,
 })
 
 // 路由跳转拦截

+ 0 - 0
src/packages/mobile/views/sign/login/index.less → src/packages/mobile/views/auth/login/index.less


+ 48 - 0
src/packages/mobile/views/auth/login/index.vue

@@ -0,0 +1,48 @@
+<template>
+  <app-view class="login">
+    <template #header>
+      <app-navbar title="登录" :show-back-button="showBackButton" />
+    </template>
+    <div class="login-logo">用户登录</div>
+    <Form @submit="formSubmit">
+      <CellGroup inset>
+        <Field v-model="user.LoginID" name="account" label="用户名" placeholder="请输入用户名"
+          :rules="[{ required: true, message: '随便输入' }]" />
+        <Field v-model="user.LoginPWD" name="password" type="password" label="密码" placeholder="请输入密码"
+          :rules="[{ required: true, message: '随便输入' }]" autocomplete="on" />
+      </CellGroup>
+      <div class="login-button">
+        <Button type="primary" :loading="loading" loading-text="正在登录..." native-type="submit" round block>登录</Button>
+      </div>
+    </Form>
+  </app-view>
+</template>
+
+<script lang="ts" setup>
+import { computed } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { Button, Field, CellGroup, Form, Dialog } from 'vant'
+import { useAuth } from '@/business/auth'
+import animateRouter from '@mobile/router/animateRouter'
+
+const { loading, user, login } = useAuth();
+const { state } = animateRouter;
+const route = useRoute()
+const router = useRouter()
+const showBackButton = computed(() => state.history.length > 1);
+
+const formSubmit = () => {
+  login().then(() => {
+    const redirect = route.query.redirect;
+    if (redirect) {
+      router.replace(redirect.toString());
+    } else {
+      router.replace('/');
+    }
+  }).catch((err) => Dialog({ message: err }))
+}
+</script>
+
+<style lang="less" scoped>
+@import './index.less';
+</style>

+ 0 - 0
src/packages/mobile/views/sign/register/index.vue → src/packages/mobile/views/auth/register/index.vue


+ 21 - 23
src/packages/mobile/views/home/components/main/index.vue

@@ -1,36 +1,34 @@
 <template>
-  <div class="home-main g-flex">
-    <app-navbar class="home-main__navbar" title="企业风管" :show-back-button="false" fixed />
-    <app-navbar title="首页" :show-back-button="false" @ready="navbarReady" fixed>
-      <template #footer>
-        <Search v-model="keyword" placeholder="请输入搜索关键词" shape="round" />
-      </template>
-    </app-navbar>
-    <app-scroll-view class="g-flex__body" :style="scrollElementStyles" v-model:scroll-top="scrollTop">
-      <PullRefresh class="home-main__container" v-model="refreshing" @refresh="onRefresh">
-        <Swipe class="banner" :autoplay="3000" indicator-color="white">
-          <SwipeItem v-for="index in 4" :key="index">{{ index }}</SwipeItem>
-        </Swipe>
-        <CellGroup title="卡片风格" v-for="index in 8" :key="index" inset>
-          <Cell title="单元格" value="内容" />
-          <Cell title="单元格" value="内容" label="描述信息" />
-        </CellGroup>
-      </PullRefresh>
-    </app-scroll-view>
-  </div>
+  <app-scroll-view class="home-main">
+    <template #beforeHeader>
+      <app-navbar title="首页" :show-back-button="false">
+        <template #footer>
+          <Search v-model="keyword" placeholder="请输入搜索关键词" shape="round" />
+        </template>
+      </app-navbar>
+    </template>
+    <template #afterHeader>
+      <app-navbar class="home-main__navbar" title="企业风管" :show-back-button="false" />
+    </template>
+    <PullRefresh class="home-main__container" v-model="refreshing" @refresh="onRefresh">
+      <Swipe class="banner" :autoplay="3000" indicator-color="white">
+        <SwipeItem v-for="index in 4" :key="index">{{ index }}</SwipeItem>
+      </Swipe>
+      <CellGroup title="卡片风格" v-for="index in 8" :key="index" inset>
+        <Cell title="单元格" value="内容" />
+        <Cell title="单元格" value="内容" label="描述信息" />
+      </CellGroup>
+    </PullRefresh>
+  </app-scroll-view>
 </template>
 
 <script lang="ts" setup>
 import { ref } from 'vue'
 import { Cell, CellGroup, Swipe, SwipeItem, Search, PullRefresh } from 'vant'
-import { useScrollVisibility } from '@/hooks/scroll-visibility'
 
 const keyword = ref('');
 const refreshing = ref(false);
 
-const { bindVisibilityElement, scrollElementStyles, scrollTop } = useScrollVisibility();
-const navbarReady = (el: HTMLElement) => bindVisibilityElement(el);
-
 const onRefresh = () => {
   setTimeout(() => {
     refreshing.value = false;

+ 6 - 4
src/packages/mobile/views/home/components/market/index.vue

@@ -1,7 +1,9 @@
 <template>
-  <div class="home-market g-flex">
-    <app-navbar title="市场" :show-back-button="false"></app-navbar>
-    <div class="home-market__container g-flex__body">
+  <app-view class="home-market">
+    <template #header>
+      <app-navbar title="市场" :show-back-button="false"></app-navbar>
+    </template>
+    <div class="home-market__container">
       <Grid :column-num="3" style="margin-bottom: .2rem;">
         <GridItem icon="photo-o" text="商品" :to="{ name: 'order' }" v-for="index in 6" :key="index" />
       </Grid>
@@ -28,7 +30,7 @@
       <Button @click="showAction = true" plain block>更换主题</Button>
     </div>
     <ActionSheet v-model:show="showAction" :actions="actions" teleport="body" cancel-text="取消" @select="themeChange" />
-  </div>
+  </app-view>
 </template>
 
 <script lang="ts" setup>

+ 6 - 4
src/packages/mobile/views/home/components/mine/index.vue

@@ -1,14 +1,16 @@
 <template>
-  <div class="home-mine g-flex">
-    <app-navbar title="我的" :show-back-button="false"></app-navbar>
-    <div class="home-mine__container g-flex__body">
+  <app-view class="home-mine">
+    <template #header>
+      <app-navbar title="我的" :show-back-button="false"></app-navbar>
+    </template>
+    <div class="home-mine__container">
       <CellGroup>
         <Cell is-link title="登录" :to="{ name: 'login' }" />
         <Cell is-link title="注册" :to="{ name: 'register' }" />
         <Cell is-link title="通知" :to="{ name: 'notice' }" />
       </CellGroup>
     </div>
-  </div>
+  </app-view>
 </template>
 
 <script lang="ts" setup>

+ 7 - 5
src/packages/mobile/views/home/components/order/index.vue

@@ -1,7 +1,9 @@
 <template>
-  <div class="home-order g-flex">
-    <app-navbar title="订单" :show-back-button="false"></app-navbar>
-    <div class="home-order__container g-flex__body">
+  <app-view class="home-order">
+    <template #header>
+      <app-navbar title="订单" :show-back-button="false"></app-navbar>
+    </template>
+    <div class="home-order__container">
       <Empty description="暂无数据" />
       <table ref="dragTable" class="app-table__body" cellspacing="0" cellpadding="0"
         style="width:100%;text-align:center;">
@@ -21,7 +23,7 @@
         </tbody>
       </table>
     </div>
-  </div>
+  </app-view>
 </template>
 
 <script lang="ts" setup>
@@ -31,7 +33,7 @@ import { queryGoodsList } from '@/services/api/goods'
 import Sortable from 'sortablejs'
 
 const dragTable = ref<HTMLElement>();
-const tableList = ref<Ermcp.Goods[]>([]);
+const tableList = ref<Ermcp.GoodsRsp[]>([]);
 
 const columns = [
   {

+ 1 - 1
src/packages/mobile/views/home/index.less

@@ -1,5 +1,5 @@
 .home {
-    >.app-tabbar {
+    &-tabbar {
         background: var(--tabbar-background) !important;
         margin-top: auto;
 

+ 1 - 1
src/packages/mobile/views/home/index.vue

@@ -3,7 +3,7 @@
     <keep-alive>
       <component class="g-flex__body" :is="components[componentId]"></component>
     </keep-alive>
-    <app-tabbar :data-list="tabList" @change="onChange" fixed />
+    <app-tabbar class="home-tabbar" :data-list="tabList" @change="onChange" fixed />
   </div>
 </template>
 

+ 19 - 14
src/packages/mobile/views/order/detail/index.vue

@@ -1,24 +1,28 @@
 <template>
-  <div class="order-detail g-flex">
-    <app-navbar title="详情" />
-    <div class="g-flex__body">
-      <app-tabs :data-list="chartCycleTypeList" :data-index="1" @change="tabChange">
-        <component :is="componentMap.get('echartsTimeline')" goodscode="cu2208"
-          v-if="selectedCycleType === ChartCycleType.Time" />
-        <component :is="componentMap.get('echartsKline')" goodscode="cu2208" :cycle-type="selectedCycleType" v-else />
-      </app-tabs>
-    </div>
-    <div class="order-detail__footer">
-      <Button @click="openComponent('trade')" type="primary" round block>挂牌求购</Button>
-    </div>
-    <component ref="childComponent" :is="componentMap.get(componentId)" @closed="closeComponent" v-if="componentId" />
-  </div>
+  <app-view class="order-detail">
+    <template #header>
+      <app-navbar title="详情" />
+    </template>
+    <app-tabs :data-list="chartCycleTypeList" :data-index="1" @change="tabChange">
+      <component :is="componentMap.get('echartsTimeline')" goodscode="cu2208"
+        v-if="selectedCycleType === ChartCycleType.Time" />
+      <component :is="componentMap.get('echartsKline')" goodscode="cu2208" :cycle-type="selectedCycleType" v-else />
+    </app-tabs>
+    <Button @click="backTo('home')">返回首页</Button>
+    <template #footer>
+      <div class="order-detail__footer">
+        <Button @click="openComponent('trade')" type="primary" round block>挂牌求购</Button>
+      </div>
+      <component ref="childComponent" :is="componentMap.get(componentId)" @closed="closeComponent" v-if="componentId" />
+    </template>
+  </app-view>
 </template>
 
 <script lang="ts" setup>
 import { defineAsyncComponent, ref } from 'vue'
 import { onBeforeRouteLeave } from 'vue-router'
 import { Button } from 'vant'
+import { useNavigation } from '@/hooks/navigation'
 import { useComponent } from '@/hooks/component'
 import { ChartCycleType, getChartCycleTypeList } from '@/constants/chart'
 import AppTabs from '@/components/base/tabs/index.vue'
@@ -30,6 +34,7 @@ const componentMap = new Map<string, unknown>([
 ]);
 
 const { componentId, openComponent, closeComponent } = useComponent();
+const { backTo } = useNavigation()
 const childComponent = ref();
 const selectedCycleType = ref(ChartCycleType.Minutes); // 当前选中的图表周期
 const chartCycleTypeList = getChartCycleTypeList();

+ 0 - 67
src/packages/mobile/views/order/index/index.vue

@@ -1,67 +0,0 @@
-<template>
-  <div class="order g-flex">
-    <app-navbar title="行情">
-      <template #footer>
-        <Search v-model="state.keyword" placeholder="请输入搜索关键词" shape="round" />
-      </template>
-    </app-navbar>
-    <app-scroll-view class="g-flex__body">
-      <PullRefresh class="order__container" v-model="state.refreshing" @refresh="onRefresh">
-        <List v-model:loading="state.loading" :finished="state.finished" finished-text="没有更多了" @load="onLoad">
-          <Cell v-for="item in state.list" :key="item" :title="item" :to="{ name: 'orderDetail', params: { id: 1 } }" />
-        </List>
-      </PullRefresh>
-    </app-scroll-view>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { reactive } from 'vue'
-import { Search, List, Cell, PullRefresh } from 'vant'
-
-const state: {
-  list: number[];
-  loading: boolean;
-  finished: boolean;
-  refreshing: boolean;
-  keyword: string;
-} = reactive({
-  list: [],
-  loading: false,
-  finished: false,
-  refreshing: false,
-  keyword: ''
-});
-
-const onLoad = () => {
-  setTimeout(() => {
-    if (state.refreshing) {
-      state.list = [];
-      state.refreshing = false;
-    }
-
-    for (let i = 0; i < 20; i++) {
-      state.list.push(state.list.length + 1);
-    }
-    state.loading = false;
-
-    if (state.list.length >= 60) {
-      state.finished = true;
-    }
-  }, 1000);
-}
-
-const onRefresh = () => {
-  // 清空列表数据
-  state.finished = false;
-
-  // 重新加载数据
-  // 将 loading 设置为 true,表示处于加载状态
-  state.loading = true;
-  onLoad();
-}
-</script>
-
-<style lang="less">
-@import './index.less';
-</style>

+ 0 - 0
src/packages/mobile/views/order/index/index.less → src/packages/mobile/views/order/main/index.less


+ 48 - 0
src/packages/mobile/views/order/main/index.vue

@@ -0,0 +1,48 @@
+<template>
+  <app-view class="order" v-model:animationend="animationend">
+    <template #header>
+      <app-navbar title="行情">
+        <template #footer>
+          <Search v-model="state.keyword" placeholder="请输入搜索关键词" shape="round" />
+        </template>
+      </app-navbar>
+    </template>
+    <app-pull-refresh v-model:loading="state.loading" v-model:dataList="state.list" :total="60" @refresh="onRefresh"
+      v-if="animationend">
+      <template #default="{ item }">
+        <Cell :title="item" :to="{ name: 'orderDetail', params: { id: 1 } }" />
+      </template>
+    </app-pull-refresh>
+  </app-view>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive } from 'vue'
+import { Search, Cell } from 'vant'
+import AppPullRefresh from '@mobile/components/base/pull-refresh/index.vue'
+
+const state: {
+  list: number[];
+  loading: boolean;
+  keyword: string;
+} = reactive({
+  list: [],
+  loading: false,
+  keyword: ''
+});
+
+const animationend = ref(false)
+
+const onRefresh = (callback?: (data: number[]) => void) => {
+  state.loading = true
+  setTimeout(() => {
+    const data = Array.from({ length: 20 }, (v, k) => k + 1)
+    callback && callback(data)
+    state.loading = false
+  }, 1000);
+}
+</script>
+
+<style lang="less">
+@import './index.less';
+</style>

+ 0 - 50
src/packages/mobile/views/sign/login/index.vue

@@ -1,50 +0,0 @@
-<template>
-  <div class="login g-flex">
-    <app-navbar title="登录" :show-back-button="showBackButton" />
-    <div class="g-flex__body">
-      <div class="login-logo">用户登录</div>
-      <Form @submit="userLogin">
-        <CellGroup inset>
-          <Field v-model="user.LoginID" name="account" label="用户名" placeholder="请输入用户名"
-            :rules="[{ required: true, message: '随便输入' }]" />
-          <Field v-model="user.LoginPWD" name="password" type="password" label="密码" placeholder="请输入密码"
-            :rules="[{ required: true, message: '随便输入' }]" autocomplete="on" />
-        </CellGroup>
-        <div class="login-button">
-          <Button type="primary" :loading="loading" loading-text="正在登录..." native-type="submit" round block>登录</Button>
-        </div>
-      </Form>
-    </div>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { computed } from 'vue'
-import { useRoute, useRouter } from 'vue-router'
-import { Button, Field, CellGroup, Form } from 'vant'
-import { notify } from '@/utils/vant'
-import { useSign } from '@/business/sign'
-import animateRouter from '@mobile/router/animateRouter'
-
-const { loading, user, signIn } = useSign();
-const { state } = animateRouter;
-const route = useRoute()
-const router = useRouter()
-const showBackButton = computed(() => state.historyStacks.length > 1);
-
-const userLogin = () => {
-  signIn().then(() => {
-    notify('登录成功', 'success')
-    const redirect = route.query.redirect;
-    if (redirect) {
-      router.replace(redirect.toString());
-    } else {
-      router.replace('/');
-    }
-  }).catch((err) => notify(err, 'danger'))
-}
-</script>
-
-<style lang="less" scoped>
-@import './index.less';
-</style>

+ 42 - 42
src/packages/pc/assets/themes/default/default.less

@@ -1,40 +1,40 @@
-[theme='default'] {
+:root {
     /* 字体大小规范 */
-    --font-x-large            : 18px;
-    --font-large              : 16px;
-    --font-medium             : 14px;
-    --font-small              : 12px;
-    --font-x-small            : 10px;
+    --font-x-large: 18px;
+    --font-large: 16px;
+    --font-medium: 14px;
+    --font-small: 12px;
+    --font-x-small: 10px;
     /* 颜色规范 */
-    --color-default           : #384048;
-    --color-primary           : #409EFF;
-    --color-secondary         : #04c786;
-    --color-info              : #999;
-    --color-border            : #eee;
+    --color-default: #384048;
+    --color-primary: #409EFF;
+    --color-secondary: #04c786;
+    --color-info: #999;
+    --color-border: #eee;
     /* 间距规范 */
-    --space-medium            : 20px;
+    --space-medium: 20px;
     /* 状态栏 */
-    --statusbar-height        : 56px;
+    --statusbar-height: 56px;
     /* 标签栏 */
-    --tabbar-active           : #374758;
-    --tabbar-hover            : #eee;
-    --tabbar-close-hover      : red;
+    --tabbar-active: #374758;
+    --tabbar-hover: #eee;
+    --tabbar-close-hover: red;
     /* 侧边栏 */
-    --sidebar-width           : 200px;
-    --sidebar-background      : #2b3a4a;
-    --sidebar-header-height   : 56px;
-    --sidebar-header-border   : 1px solid #374758;
-    --sidebar-menu-inline     : #263442;
-    --sidebar-menu-item       : #8699ad;
-    --sidebar-menu-item-hover : #374758;
+    --sidebar-width: 200px;
+    --sidebar-background: #2b3a4a;
+    --sidebar-header-height: 56px;
+    --sidebar-header-border: 1px solid #374758;
+    --sidebar-menu-inline: #263442;
+    --sidebar-menu-item: #8699ad;
+    --sidebar-menu-item-hover: #374758;
     --sidebar-menu-item-active: #278eff;
 
     .el-form {
         &-item {
             &--col {
                 display: flex;
-                width  : 100%;
-                gap    : 10px;
+                width: 100%;
+                gap: 10px;
             }
 
             &:last-child {
@@ -43,7 +43,7 @@
         }
 
         &--horizontal {
-            display  : flex;
+            display: flex;
             flex-wrap: wrap;
 
             .el-form-item {
@@ -54,7 +54,7 @@
                 }
 
                 &__content {
-                    align-items  : flex-start;
+                    align-items: flex-start;
                     padding-right: 48px;
                 }
 
@@ -71,37 +71,37 @@
 
     .app-tabs {
         &__navbar {
-            z-index         : 10;
-            display         : flex;
-            align-items     : center;
+            z-index: 10;
+            display: flex;
+            align-items: center;
             background-color: #fff;
-            border-top      : 1px solid #f2f2f2;
-            box-shadow      : 0 2px 16px 0 rgba(0, 0, 0, .1);
-            padding         : 8px 20px 0 20px;
+            border-top: 1px solid #f2f2f2;
+            box-shadow: 0 2px 16px 0 rgba(0, 0, 0, .1);
+            padding: 8px 20px 0 20px;
 
             .tabs {
                 &-item {
-                    height                 : 40px;
-                    line-height            : 40px;
-                    color                  : #777;
-                    border-top-left-radius : 4px;
+                    height: 40px;
+                    line-height: 40px;
+                    color: #777;
+                    border-top-left-radius: 4px;
                     border-top-right-radius: 4px;
-                    cursor                 : pointer;
-                    padding                : 0 20px;
+                    cursor: pointer;
+                    padding: 0 20px;
 
                     &:not(:first-child) {
                         margin-left: 4px;
                     }
 
                     &:hover {
-                        color           : inherit;
+                        color: inherit;
                         background-color: var(--tabbar-hover);
                     }
 
                     &.is-active {
-                        color           : #fff !important;
+                        color: #fff !important;
                         background-color: var(--tabbar-active);
-                        border-bottom   : 0;
+                        border-bottom: 0;
                     }
                 }
             }

+ 3 - 3
src/packages/pc/components/layouts/header/index.vue

@@ -32,7 +32,7 @@
                 <template #dropdown>
                     <el-dropdown-menu>
                         <!-- <el-dropdown-item icon="Key">修改密码</el-dropdown-item> -->
-                        <el-dropdown-item icon="SwitchButton" @click="signOut()">退出登录</el-dropdown-item>
+                        <el-dropdown-item icon="SwitchButton" @click="logout()">退出登录</el-dropdown-item>
                     </el-dropdown-menu>
                 </template>
             </el-dropdown>
@@ -47,7 +47,7 @@ import { ref, onMounted, defineAsyncComponent } from 'vue'
 import { useRouter } from 'vue-router'
 import client from '@/utils/client'
 import { useUserStore } from '@/stores'
-import { useSign } from '@/business/sign'
+import { useAuth } from '@/business/auth'
 import { useComponent } from '@/hooks/component'
 import { useNotice } from '@/business/notice'
 import AppIcon from '@pc/components/base/icon/index.vue'
@@ -61,7 +61,7 @@ const componentMap = new Map<string, unknown>([
 const { componentId, openComponent, closeComponent } = useComponent()
 const { dataList, unreadList, getNoticeList } = useNotice()
 const { state } = client
-const { signOut } = useSign()
+const { logout } = useAuth()
 const { getAccountName } = useUserStore()
 const router = useRouter()
 const fullScreen = ref(false)

+ 2 - 2
src/packages/pc/components/layouts/main/index.vue

@@ -13,10 +13,10 @@
 
 <script lang="ts" setup>
 import { shallowRef } from 'vue'
-import { useAuth } from '@/hooks/auth'
+import { useMenu } from '@/hooks/menu'
 import AppTabs from '@/components/base/tabs/index.vue'
 
-const { route, router, getChildrenMenus } = useAuth()
+const { route, router, getChildrenMenus } = useMenu()
 const parentRoute = route.matched[route.matched.length - 2] // 父级路由信息
 const secondMenus = shallowRef<Ermcp.UserMenu[]>([]) // 二级菜单
 const dataIndex = shallowRef(0) // 选中的标签

+ 2 - 2
src/packages/pc/components/layouts/sidebar/index.vue

@@ -15,7 +15,7 @@
 
 <script lang="ts" setup>
 import { watch } from 'vue'
-import { useAuth } from '@/hooks/auth'
+import { useMenu } from '@/hooks/menu'
 import client from '@/utils/client'
 import AppSidemenu from '../sidemenu/index.vue'
 
@@ -26,7 +26,7 @@ defineProps({
   collapse: Boolean,
 })
 
-const { router, getChildrenMenus } = useAuth()
+const { router, getChildrenMenus } = useMenu()
 const { state } = client
 const year = new Date().getFullYear()
 

+ 2 - 2
src/packages/pc/components/layouts/sidemenu/index.vue

@@ -11,12 +11,12 @@
 
 <script lang="ts" setup>
 import { computed } from 'vue'
-import { useAuth } from '@/hooks/auth'
+import { useMenu } from '@/hooks/menu'
 import AppIcon from '@pc/components/base/icon/index.vue'
 import AppSubmenu from './submenu.vue'
 
 const emit = defineEmits(['click'])
-const { route, router, getMenus } = useAuth()
+const { route, router, getMenus } = useMenu()
 const level = 1 // 菜单层级
 const menus = getMenus(level) // 如果是无限级菜单,activeMenu 应该直接返回 route.name
 

+ 2 - 2
src/packages/pc/components/modules/auth-component/index.vue

@@ -18,7 +18,7 @@
 
 <script lang="ts" setup>
 import { shallowRef, PropType, onMounted, useAttrs } from 'vue'
-import { useAuth } from '@/hooks/auth'
+import { useMenu } from '@/hooks/menu'
 
 const props = defineProps({
     code: String,
@@ -40,7 +40,7 @@ const props = defineProps({
     },
 })
 
-const { componentMap, getAuthComponent } = useAuth(props.code)
+const { componentMap, getAuthComponent } = useMenu(props.code)
 const { onChange } = useAttrs()
 const componentId = shallowRef<string>()
 const dataList = shallowRef<Ermcp.UserMenu[]>([]) // 数据列表

+ 2 - 2
src/packages/pc/components/modules/auth-operation/index.vue

@@ -46,7 +46,7 @@
 
 <script lang="ts" setup>
 import { onMounted, onUnmounted, onDeactivated, shallowRef, PropType, computed, watch } from 'vue'
-import { useAuth } from '@/hooks/auth'
+import { useMenu } from '@/hooks/menu'
 
 const emit = defineEmits(['click', 'closed'])
 
@@ -79,7 +79,7 @@ const props = defineProps({
     },
 })
 
-const { componentMap, getAuthButton } = useAuth(props.code);
+const { componentMap, getAuthButton } = useMenu(props.code);
 const componentId = shallowRef<string>();
 const contextmenuOption = shallowRef(props.contextmenu);
 const auth = shallowRef<Ermcp.UserMenu[]>([]);

+ 14 - 14
src/packages/pc/router/historyRouter.ts

@@ -9,7 +9,7 @@ interface HistoryStack {
 }
 
 interface HistoryState {
-    historyStacks: HistoryStack[]; // 已访问的路由列表
+    history: HistoryStack[]; // 已访问的路由列表
     historyIndex: number; // 当前历史索引位置
     excludeViews: string[]; // 不缓存的页面
     actionName: '' | 'push' | 'replace' | 'forward' | 'back'; // 当前路由动作
@@ -17,7 +17,7 @@ interface HistoryState {
 
 export default new (class {
     private _state = ref<HistoryState>({
-        historyStacks: [],
+        history: [],
         historyIndex: 0,
         excludeViews: [],
         actionName: '',
@@ -102,28 +102,28 @@ export default new (class {
      * @param route 
      */
     private addHistory = (route: HistoryStack) => {
-        const { historyStacks, historyIndex, excludeViews, actionName } = toRefs(this._state.value);
-        const index = historyStacks.value.findIndex((e) => e.name === route.name);
+        const { history, historyIndex, excludeViews, actionName } = toRefs(this._state.value);
+        const index = history.value.findIndex((e) => e.name === route.name);
 
         if (index > -1) {
-            historyStacks.value[index] = route;
+            history.value[index] = route;
             historyIndex.value = index;
         } else {
             if (actionName.value === 'replace') {
-                const lastIndex = historyStacks.value.length - 1;
-                const lastView = historyStacks.value[lastIndex];
+                const lastIndex = history.value.length - 1;
+                const lastView = history.value[lastIndex];
 
                 if (lastView) {
                     excludeViews.value.push(lastView.name as string);
-                    historyStacks.value[lastIndex] = route; // 更新最后一条记录
+                    history.value[lastIndex] = route; // 更新最后一条记录
                 } else {
-                    historyStacks.value.push(route);
+                    history.value.push(route);
                 }
             } else {
                 // 忽略重定向的页面
                 if (!route.redirected) {
-                    historyStacks.value.push(route);
-                    historyIndex.value = historyStacks.value.length - 1;
+                    history.value.push(route);
+                    historyIndex.value = history.value.length - 1;
                 }
             }
         }
@@ -138,12 +138,12 @@ export default new (class {
      */
     removeHistory = (routeName?: string) => {
         if (routeName) {
-            const { historyStacks, excludeViews } = toRefs(this._state.value);
-            const index = historyStacks.value.findIndex((e) => e.name === routeName);
+            const { history, excludeViews } = toRefs(this._state.value);
+            const index = history.value.findIndex((e) => e.name === routeName);
             excludeViews.value.push(routeName);
 
             if (index > -1) {
-                historyStacks.value.splice(index, 1);
+                history.value.splice(index, 1);
                 sessionStorage.setItem('historyState', JSON.stringify(this._state.value));
             }
         }

+ 1 - 1
src/packages/pc/router/index.ts

@@ -13,7 +13,7 @@ const routes: Array<RouteRecordRaw> = [
     {
         path: '/login',
         name: 'login',
-        component: () => import('../views/sign/login/index.vue'),
+        component: () => import('../views/auth/login/index.vue'),
         meta: {
             title: "登陆",
         },

+ 0 - 0
src/packages/pc/views/sign/components/layout/index.less → src/packages/pc/views/auth/components/layout/index.less


+ 0 - 0
src/packages/pc/views/sign/components/layout/index.vue → src/packages/pc/views/auth/components/layout/index.vue


+ 0 - 0
src/packages/pc/views/sign/login/index.less → src/packages/pc/views/auth/login/index.less


+ 5 - 5
src/packages/pc/views/sign/login/index.vue → src/packages/pc/views/auth/login/index.vue

@@ -12,7 +12,7 @@
         <el-checkbox label="记住账号"></el-checkbox>
       </el-form-item>
       <el-form-item>
-        <el-button class="submit" type="primary" :loading="loading" @click="userLogin">
+        <el-button class="submit" type="primary" :loading="loading" @click="formSubmit">
           <span v-if="loading">正在登录</span>
           <span v-else>登录</span>
         </el-button>
@@ -27,10 +27,10 @@ import { ref } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { ElMessage } from 'element-plus'
 import type { FormInstance, FormRules } from 'element-plus'
-import { useSign } from '@/business/sign'
+import { useAuth } from '@/business/auth'
 import SignLayout from '../components/layout/index.vue'
 
-const { loading, user, signIn } = useSign()
+const { loading, user, login } = useAuth()
 const route = useRoute()
 const router = useRouter()
 const formRef = ref<FormInstance>()
@@ -43,10 +43,10 @@ const formRules: FormRules = {
   ]
 }
 
-const userLogin = () => {
+const formSubmit = () => {
   formRef.value?.validate((valid) => {
     if (valid) {
-      signIn().then(() => {
+      login().then(() => {
         const redirect = route.query.redirect;
         if (redirect) {
           router.replace(redirect.toString());

+ 2 - 2
src/packages/pc/views/system/role/components/auth/index.vue

@@ -18,7 +18,7 @@
 
 <script lang="ts" setup>
 import { ref, PropType } from 'vue'
-import { useAuth } from '@/hooks/auth'
+import { useMenu } from '@/hooks/menu'
 import AppDrawer from '@pc/components/base/drawer/index.vue'
 
 defineProps({
@@ -28,7 +28,7 @@ defineProps({
     }
 })
 
-const { userMenus } = useAuth()
+const { userMenus } = useMenu()
 const show = ref(true)
 </script>
 

+ 2 - 2
src/packages/pc/views/trade/buy/components/details/index.vue

@@ -33,7 +33,7 @@
 
 <script lang="ts" setup>
 import { computed, PropType } from 'vue'
-import { useAuth } from '@/hooks/auth'
+import { useMenu } from '@/hooks/menu'
 import { useLoginStore, usePerformanceStore } from '@/stores'
 import AppPerformanceRule from '@pc/components/modules/performance-rule/index.vue'
 
@@ -46,7 +46,7 @@ const props = defineProps({
 })
 
 const { getUserId } = useLoginStore()
-const { componentMap, getAuthComponent } = useAuth(props.code)
+const { componentMap, getAuthComponent } = useMenu(props.code)
 const { getPerformanceTemplateById } = usePerformanceStore()
 
 // 不能购买自己发布的求购

+ 10 - 10
src/services/api/account/index.ts

@@ -1,60 +1,60 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 
 /**
  * 用户登录
  */
-export function login(params: TradeRequest<Proto.LoginReq, Proto.LoginRsp>) {
+export function login(params: TradeParams<Proto.LoginReq, Proto.LoginRsp>) {
     return tradeServerRequest('LoginReq', 'LoginRsp', params);
 }
 
 /**
  * 用户令牌校验
  */
-export function tokenCheck(params: TradeRequest<Proto.TokenCheckReq, Proto.TokenCheckRsp>) {
+export function tokenCheck(params: TradeParams<Proto.TokenCheckReq, Proto.TokenCheckRsp>) {
     return tradeServerRequest('TokenCheckReq', 'TokenCheckRsp', params);
 }
 
 /**
  * 修改密码
  */
-export function modifyPassword(params: TradeRequest<Proto.ModifyPwdReq, Proto.ModifyPwdRsp>) {
+export function modifyPassword(params: TradeParams<Proto.ModifyPwdReq, Proto.ModifyPwdRsp>) {
     return tradeServerRequest('ModifyPwdReq', 'ModifyPwdRsp', params);
 }
 
 /**
  * 查询用户菜单
  */
-export function queryAccountMenu(params: HttpRequest<{ rsp: Ermcp.UserMenu[] }>) {
+export function queryAccountMenu(params: HttpParams<{ rsp: Ermcp.UserMenu[] }>) {
     return httpRequest('/account/menu', 'get', params);
 }
 
 /**
  * 查询登录ID
  */
-export function queryLoginId(params: HttpRequest<{ req: { username: string }, rsp: string }>) {
+export function queryLoginId(params: HttpParams<{ req: { username: string }, rsp: string }>) {
     return httpRequest('/User/GetLoginID', 'get', params);
 }
 
 /**
  * 查询登录账户配置信息
  */
-export function queryLoginData(params: HttpRequest<{ req: Ermcp.LoginQueryReq, rsp: Ermcp.LoginQueryRsp }>) {
+export function queryLoginData(params: HttpParams<{ req: Ermcp.LoginQueryReq, rsp: Ermcp.LoginQueryRsp }>) {
     return httpRequest('/User/LoginQuery', 'get', params);
 }
 
 /**
  * 查询资金账户信息
  */
-export function queryTaAccounts(params: HttpRequest<{ req: Ermcp.TaAccountsReq, rsp: Ermcp.TaAccountsRsp[] }>) {
+export function queryTaAccounts(params: HttpParams<{ req: Ermcp.TaAccountsReq, rsp: Ermcp.TaAccountsRsp[] }>) {
     return httpRequest('/TaAccount/GetTaAccounts', 'get', params);
 }
 
 /**
  * 查询账户角色
  */
-export function queryAccountRole(params: HttpRequest<{ rsp: Ermcp.UserRole[] }>) {
+export function queryAccountRole(params: HttpParams<{ rsp: Ermcp.UserRole[] }>) {
     return httpRequest('/account/role', 'get', params);
 }

+ 10 - 10
src/services/api/bank/index.ts

@@ -1,60 +1,60 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 
 /**
  * 银行签约
  */
-export function t2bBankSign(params: TradeRequest<Partial<Proto.t2bBankSignReq>, Proto.t2bBankSignRsp>) {
+export function t2bBankSign(params: TradeParams<Partial<Proto.t2bBankSignReq>, Proto.t2bBankSignRsp>) {
     return tradeServerRequest('t2bBankSignReq', 't2bBankSignRsp', params);
 }
 
 /**
  * 银行解约
  */
-export function t2bBankCancelSign(params: TradeRequest<Proto.t2bBankCancelSignReq, Proto.t2bBankCancelSignRsp>) {
+export function t2bBankCancelSign(params: TradeParams<Proto.t2bBankCancelSignReq, Proto.t2bBankCancelSignRsp>) {
     return tradeServerRequest('t2bBankCancelSignReq', 't2bBankCancelSignRsp', params);
 }
 
 /**
  * 出金申请
  */
-export function t2bBankWithdraw(params: TradeRequest<Partial<Proto.t2bBankWithdrawReq>, Proto.t2bBankWithdrawRsp>) {
+export function t2bBankWithdraw(params: TradeParams<Partial<Proto.t2bBankWithdrawReq>, Proto.t2bBankWithdrawRsp>) {
     return tradeServerRequest('t2bBankWithdrawReq', 't2bBankWithdrawRsp', params);
 }
 
 /**
  * 入金申请
  */
-export function t2bBankDeposit(params: TradeRequest<Partial<Proto.t2bBankDepositReq>, Proto.t2bBankDepositRsp>) {
+export function t2bBankDeposit(params: TradeParams<Partial<Proto.t2bBankDepositReq>, Proto.t2bBankDepositRsp>) {
     return tradeServerRequest('t2bBankDepositReq', 't2bBankDepositRsp', params);
 }
 
 /**
  * 查询托管银行
  */
-export function queryCusBankSignBank(params: HttpRequest<{ rsp: Ermcp.CusBankSignBankRsp[] }>) {
+export function queryCusBankSignBank(params: HttpParams<{ rsp: Ermcp.CusBankSignBankRsp[] }>) {
     return httpRequest('/Qhj/QueryCusBankSignBank', 'get', params);
 }
 
 /**
  * 查询开户行
  */
-export function queryBankInfo(params: HttpRequest<{ rsp: Ermcp.BankInfoRsp[] }>) {
+export function queryBankInfo(params: HttpParams<{ rsp: Ermcp.BankInfoRsp[] }>) {
     return httpRequest('/Qhj/QueryBankInfo', 'get', params);
 }
 
 /**
  * 查询签约银行信息(提现账户管理)
  */
-export function queryBankAccountSign(params: HttpRequest<{ req: Ermcp.BankAccountSignReq, rsp: Ermcp.BankAccountSignRsp[] }>) {
+export function queryBankAccountSign(params: HttpParams<{ req: Ermcp.BankAccountSignReq, rsp: Ermcp.BankAccountSignRsp[] }>) {
     return httpRequest('/Qhj/QueryBankAccountSign', 'get', params);
 }
 
 /**
  * 查询充值提现
  */
-export function queryAccountInOutApply(params: HttpRequest<{ req: Ermcp.AccountInOutApplyReq, rsp: Ermcp.AccountOutInApplyRsp[] }>) {
+export function queryAccountInOutApply(params: HttpParams<{ req: Ermcp.AccountInOutApplyReq, rsp: Ermcp.AccountOutInApplyRsp[] }>) {
     return httpRequest('/Qhj/QueryAccountInOutApply', 'get', params);
 }

+ 16 - 16
src/services/api/common/index.ts

@@ -1,107 +1,107 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 
 /**
  * 首页统计数据
  */
-export function homeData(params: HttpRequest<{ req: Ermcp.HomeDataReq, rsp: Ermcp.HomeDataRsp }>) {
+export function homeData(params: HttpParams<{ req: Ermcp.HomeDataReq, rsp: Ermcp.HomeDataRsp }>) {
     return httpRequest('/Guangzuan/HomeData', 'get', params);
 }
 
 /**
  * 获取服务器时间
  */
-export function getServerTime(params: HttpRequest<{ rsp: string }>) {
+export function getServerTime(params: HttpParams<{ rsp: string }>) {
     return httpRequest('/Common/GetServerTime', 'get', params);
 }
 
 /**
  * 查询交易端列表头信息
  */
-export function queryTableDefine(params: HttpRequest<{ req: Ermcp.TableDefineReq, rsp: Ermcp.TableDefineRsp[] }>) {
+export function queryTableDefine(params: HttpParams<{ req: Ermcp.TableDefineReq, rsp: Ermcp.TableDefineRsp[] }>) {
     return httpRequest('/Common/QueryTableDefine', 'get', params);
 }
 
 /**
  * 查询所有枚举信息
  */
-export function queryAllEnums(params: HttpRequest<{ req: Ermcp.EnumReq, rsp: Ermcp.EnumRsp[] }>) {
+export function queryAllEnums(params: HttpParams<{ req: Ermcp.EnumReq, rsp: Ermcp.EnumRsp[] }>) {
     return httpRequest('/Common/GetAllEnums', 'get', params);
 }
 
 /**
  * 获取菜单表数据
  */
-export function queryNewFuncmenu(params: HttpRequest<{ req: Ermcp.NewFuncmenuReq, rsp: Ermcp.NewFuncmenuRsp[] }>) {
+export function queryNewFuncmenu(params: HttpParams<{ req: Ermcp.NewFuncmenuReq, rsp: Ermcp.NewFuncmenuRsp[] }>) {
     return httpRequest('/Common/FindNewFuncmenu', 'get', params);
 }
 
 /**
  * 插入菜单表数据
  */
-export function insertNewFuncmenu(params: HttpRequest<{ req: Partial<Ermcp.NewFuncmenuRsp> }>) {
+export function insertNewFuncmenu(params: HttpParams<{ req: Partial<Ermcp.NewFuncmenuRsp> }>) {
     return httpRequest('/Common/InsertNewFuncmenu', 'post', params);
 }
 
 /**
  * 更新菜单表数据
  */
-export function updateNewFuncmenu(params: HttpRequest<{ req: Partial<Ermcp.NewFuncmenuRsp> }>) {
+export function updateNewFuncmenu(params: HttpParams<{ req: Partial<Ermcp.NewFuncmenuRsp> }>) {
     return httpRequest('/Common/UpdateNewFuncmenu', 'put', params);
 }
 
 /**
  * 删除菜单表数据
  */
-export function deleteNewFuncmenu(params: HttpRequest<{ req: Partial<Ermcp.NewFuncmenuRsp> }>) {
+export function deleteNewFuncmenu(params: HttpParams<{ req: Partial<Ermcp.NewFuncmenuRsp> }>) {
     return httpRequest('/Common/DeleteNewFuncmenu', 'delete', params);
 }
 
 /**
  * 查询汇率信息
  */
-export function queryRates(params: HttpRequest<{ req: Ermcp.RatesReq, rsp: Ermcp.RatesRsp[] }>) {
+export function queryRates(params: HttpParams<{ req: Ermcp.RatesReq, rsp: Ermcp.RatesRsp[] }>) {
     return httpRequest('/Common/QueryRates', 'get', params);
 }
 
 /**
  * 通知公告系统消息查询
  */
-export function queryNotice(params: HttpRequest<{ req: Ermcp.NoticeReq, rsp: Ermcp.NoticeRsp[] }>) {
+export function queryNotice(params: HttpParams<{ req: Ermcp.NoticeReq, rsp: Ermcp.NoticeRsp[] }>) {
     return httpRequest('/Common/QueryNotice', 'get', params);
 }
 
 /**
  * 通知公告设置已读
  */
-export function postNoticeReaded(params: HttpRequest<{ req: Ermcp.NoticeReadedReq }>) {
+export function postNoticeReaded(params: HttpParams<{ req: Ermcp.NoticeReadedReq }>) {
     return httpRequest('/Common/NoticeReaded', 'post', params);
 }
 
 /**
  * 获取数据库错误信息
  */
-export function queryErrorInfos(params: HttpRequest<{ req: Ermcp.ErrorInfosReq, rsp: Ermcp.ErrorInfosRsp[] }>) {
+export function queryErrorInfos(params: HttpParams<{ req: Ermcp.ErrorInfosReq, rsp: Ermcp.ErrorInfosRsp[] }>) {
     return httpRequest('/Common/QueryErrorInfos', 'get', params);
 }
 
 /**
  * 钻石价格计算器
  */
-export function priceCalc(params: HttpRequest<{ req: Partial<Ermcp.PriceCalcReq>, rsp: Ermcp.PriceCalcRsp[] }>) {
+export function priceCalc(params: HttpParams<{ req: Partial<Ermcp.PriceCalcReq>, rsp: Ermcp.PriceCalcRsp[] }>) {
     return httpRequest('/Guangzuan/PriceCalc', 'get', params);
 }
 
 /**
  * Rapaport最新报价表(广钻)
  */
-export function gzCertAddressConfig(params: HttpRequest<{ rsp: Ermcp.GzCertAddressConfigRsp[] }>) {
+export function gzCertAddressConfig(params: HttpParams<{ rsp: Ermcp.GzCertAddressConfigRsp[] }>) {
     return httpRequest('/Guangzuan/GzCertAddressConfig', 'get', params);
 }
 
 /**
  * 钻石证书地址参数
  */
-export function gzCertAddressParam(params: HttpRequest<{ rsp: Ermcp.GzCertAddressParamRsp[] }>) {
+export function gzCertAddressParam(params: HttpParams<{ rsp: Ermcp.GzCertAddressParamRsp[] }>) {
     return httpRequest('/Guangzuan/GzCertAddressParam', 'get', params);
 }

+ 12 - 12
src/services/api/customs/index.ts

@@ -1,74 +1,74 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 
 /**
  * 查询出境检测单据
  */
-export function queryGZCJJCOrder(params: HttpRequest<{ req: Ermcp.GZCJJCOrderReq, rsp: Ermcp.GZCJJCOrderRsp[] }>) {
+export function queryGZCJJCOrder(params: HttpParams<{ req: Ermcp.GZCJJCOrderReq, rsp: Ermcp.GZCJJCOrderRsp[] }>) {
     return httpRequest('/Guangzuan/QueryGZCJJCOrder', 'get', params);
 }
 
 /**
  * 查询出境检测单据明细(批次信息)
  */
-export function queryGZCJJCOrderDetail(params: HttpRequest<{ req: Ermcp.GZCJJCOrderDetailReq, rsp: Ermcp.GZCJJCOrderDetailRsp[] }>) {
+export function queryGZCJJCOrderDetail(params: HttpParams<{ req: Ermcp.GZCJJCOrderDetailReq, rsp: Ermcp.GZCJJCOrderDetailRsp[] }>) {
     return httpRequest('/Guangzuan/QueryGZCJJCOrderDetail', 'get', params);
 }
 
 /**
  * 查询保税服务单据
  */
-export function queryGZBSFWOrder(params: HttpRequest<{ req: Ermcp.GZBSFWOrderReq, rsp: Ermcp.GZBSFWOrderRsp[] }>) {
+export function queryGZBSFWOrder(params: HttpParams<{ req: Ermcp.GZBSFWOrderReq, rsp: Ermcp.GZBSFWOrderRsp[] }>) {
     return httpRequest('/Guangzuan/QueryGZBSFWOrder', 'get', params);
 }
 
 /**
  * 保税服务单据操作信息
  */
-export function gzBSFWOrderOperate(params: HttpRequest<{ req: Ermcp.GZBSFWOrderOperateReq, rsp: Ermcp.GZBSFWOrderOperateRsp[] }>) {
+export function gzBSFWOrderOperate(params: HttpParams<{ req: Ermcp.GZBSFWOrderOperateReq, rsp: Ermcp.GZBSFWOrderOperateRsp[] }>) {
     return httpRequest('/Guangzuan/GZBSFWOrderOperate', 'get', params);
 }
 
 /**
  * 查询保税服务单据明细
  */
-export function queryGZBSFWOrderDetail(params: HttpRequest<{ req: Ermcp.GZBSFWOrderDetailReq, rsp: Ermcp.GZBSFWOrderDetailRsp[] }>) {
+export function queryGZBSFWOrderDetail(params: HttpParams<{ req: Ermcp.GZBSFWOrderDetailReq, rsp: Ermcp.GZBSFWOrderDetailRsp[] }>) {
     return httpRequest('/Guangzuan/QueryGZBSFWOrderDetail', 'get', params);
 }
 
 /**
  * 出境保税单据文件
  */
-export function queryGZCJBSOrderFile(params: HttpRequest<{ req: Ermcp.GZCJBSOrderFileReq, rsp: Ermcp.GZCJBSOrderFileRsp[] }>) {
+export function queryGZCJBSOrderFile(params: HttpParams<{ req: Ermcp.GZCJBSOrderFileReq, rsp: Ermcp.GZCJBSOrderFileRsp[] }>) {
     return httpRequest('/Guangzuan/QueryGZCJBSOrderFile', 'get', params);
 }
 
 /**
  * 出境检测申请
  */
-export function cjjcApply(params: TradeRequest<Proto.CJJCApplyReq, Proto.CJJCApplyRsp>) {
+export function cjjcApply(params: TradeParams<Proto.CJJCApplyReq, Proto.CJJCApplyRsp>) {
     return tradeServerRequest('CJJCApplyReq', 'CJJCApplyRsp', params);
 }
 
 /**
  * 出境检测会员操作
  */
-export function cjjcMemberOperate(params: TradeRequest<Proto.CJJCMemberOperateReq, Proto.CJJCMemberOperateRsp>) {
+export function cjjcMemberOperate(params: TradeParams<Proto.CJJCMemberOperateReq, Proto.CJJCMemberOperateRsp>) {
     return tradeServerRequest('CJJCMemberOperateReq', 'CJJCMemberOperateRsp', params);
 }
 
 /**
  * 出境检测确认预付款生成文件
  */
-export function cjjcConfirmMarginBuildFileReq(params: TradeRequest<Proto.CJJCConfirmMarginBuildFileReq, Proto.CJJCConfirmMarginBuildFileRsp>) {
+export function cjjcConfirmMarginBuildFileReq(params: TradeParams<Proto.CJJCConfirmMarginBuildFileReq, Proto.CJJCConfirmMarginBuildFileRsp>) {
     return tradeServerRequest('CJJCConfirmMarginBuildFileReq', 'BSFWMemberOperateRsp', params);
 }
 
 /**
  * 保税服务会员操作
  */
-export function bsfwMemberOperate(params: TradeRequest<Proto.BSFWMemberOperateReq, Proto.BSFWMemberOperateRsp>) {
+export function bsfwMemberOperate(params: TradeParams<Proto.BSFWMemberOperateReq, Proto.BSFWMemberOperateRsp>) {
     return tradeServerRequest('BSFWMemberOperateReq', 'BSFWMemberOperateRsp', params);
 }

+ 4 - 4
src/services/api/favorite/index.ts

@@ -1,19 +1,19 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 import { Market } from '@/constants/market'
 
 /**
  * 查询我的收藏
  */
-export function queryMyFavorite(params: HttpRequest<{ req: Ermcp.MyFavoriteReq, rsp: Ermcp.MyFavoriteRsp[] }>) {
+export function queryMyFavorite(params: HttpParams<{ req: Ermcp.MyFavoriteReq, rsp: Ermcp.MyFavoriteRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyFavorite', 'get', params);
 }
 
 /**
  * 商品收藏操作
  */
-export function goodsFavoriteOperate(params: TradeRequest<Proto.GoodsFavoriteOperateReq, Proto.GoodsFavoriteOperateRsp>) {
+export function goodsFavoriteOperate(params: TradeParams<Proto.GoodsFavoriteOperateReq, Proto.GoodsFavoriteOperateRsp>) {
     return tradeServerRequest('GoodsFavoriteOperateReq', 'GoodsFavoriteOperateRsp', params, Market.GZ);
 }

+ 7 - 7
src/services/api/goods/index.ts

@@ -1,40 +1,40 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 import { Market } from '@/constants/market'
 
 /**
  * 查询商品列表
  */
-export function queryGoodsList(params: HttpRequest<{ rsp: Ermcp.GoodsRsp[] }>) {
+export function queryGoodsList(params: HttpParams<{ rsp: Ermcp.GoodsRsp[] }>) {
     return httpRequest('/goods', 'get', params);
 }
 
 /**
  * 查询钻石列表
  */
-export function queryDiamondList(params: HttpRequest<{ req: Ermcp.MyWRPositionReq, rsp: Ermcp.MyWRPositionRsp[] }>) {
+export function queryDiamondList(params: HttpParams<{ req: Ermcp.MyWRPositionReq, rsp: Ermcp.MyWRPositionRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyWRPosition', 'get', params);
 }
 
 /**
  * 获取钻石详情
  */
-export function queryDiamondDetails(params: HttpRequest<{ req: Ermcp.DiamondDetailsReq, rsp: Ermcp.DiamondDetailsRsp }>) {
+export function queryDiamondDetails(params: HttpParams<{ req: Ermcp.DiamondDetailsReq, rsp: Ermcp.DiamondDetailsRsp }>) {
     return httpRequest('/Guangzuan/GetGoods', 'get', params);
 }
 
 /**
  * 新增钻石商品
  */
-export function addDiamond(params: TradeRequest<Proto.AddZSGoodsReq, Proto.AddZSGoodsRsp>) {
+export function addDiamond(params: TradeParams<Proto.AddZSGoodsReq, Proto.AddZSGoodsRsp>) {
     return tradeServerRequest('AddZSGoodsReq', 'AddZSGoodsRsp', params, Market.GZ);
 }
 
 /**
  * 钻石出库申请
  */
-export function receiptZSOutApply(params: TradeRequest<Proto.ReceiptZSOutApplyReq, Proto.ReceiptZSOutApplyRsp>) {
+export function receiptZSOutApply(params: TradeParams<Proto.ReceiptZSOutApplyReq, Proto.ReceiptZSOutApplyRsp>) {
     return tradeServerRequest('ReceiptZSOutApplyReq', 'ReceiptZSOutApplyRsp', params, 4);
 }

+ 10 - 10
src/services/api/performance/index.ts

@@ -1,60 +1,60 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 
 /**
  * 履约违约申请
  */
-export function performanceContractedApply(params: TradeRequest<Proto.PerformanceContractedApplyReq, Proto.PerformanceContractedApplyRsp>) {
+export function performanceContractedApply(params: TradeParams<Proto.PerformanceContractedApplyReq, Proto.PerformanceContractedApplyRsp>) {
     return tradeServerRequest('PerformanceContractedApplyReq', 'PerformanceContractedApplyRsp', params);
 }
 
 /**
  * 履约延期申请
  */
-export function performanceDelayApply(params: TradeRequest<Proto.PerformanceDelayApplyReq, Proto.PerformanceDelayApplyRsp>) {
+export function performanceDelayApply(params: TradeParams<Proto.PerformanceDelayApplyReq, Proto.PerformanceDelayApplyRsp>) {
     return tradeServerRequest('PerformanceDelayApplyReq', 'PerformanceDelayApplyRsp', params);
 }
 
 /**
  * 履约手动申请
  */
-export function performanceManualConfirm(params: TradeRequest<Proto.PerformanceManualConfirmReq, Proto.PerformanceManualConfirmRsp>) {
+export function performanceManualConfirm(params: TradeParams<Proto.PerformanceManualConfirmReq, Proto.PerformanceManualConfirmRsp>) {
     return tradeServerRequest('PerformanceManualConfirmReq', 'PerformanceManualConfirmRsp', params);
 }
 
 /**
  * 履约修改联络信息
  */
-export function performanceModifyContact(params: TradeRequest<Proto.PerformanceModifyContactReq, Proto.PerformanceModifyContactRsp>) {
+export function performanceModifyContact(params: TradeParams<Proto.PerformanceModifyContactReq, Proto.PerformanceModifyContactRsp>) {
     return tradeServerRequest('PerformanceModifyContactReq', 'PerformanceModifyContactRsp', params);
 }
 
 /**
  * 查询我的履约
  */
-export function queryMyPerformance(params: HttpRequest<{ req: Ermcp.MyPerformancReq, rsp: Ermcp.MyPerformancRsp[] }>) {
+export function queryMyPerformance(params: HttpParams<{ req: Ermcp.MyPerformancReq, rsp: Ermcp.MyPerformancRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyPerformanc', 'get', params);
 }
 
 /**
  * 查询履约模板
  */
-export function queryPermancePlanTmp(params: HttpRequest<{ req: Ermcp.PermancePlanTmpReq, rsp: Ermcp.PermancePlanTmpRsp[] }>) {
+export function queryPermancePlanTmp(params: HttpParams<{ req: Ermcp.PermancePlanTmpReq, rsp: Ermcp.PermancePlanTmpRsp[] }>) {
     return httpRequest('/WrTrade2/QueryPermancePlanTmp', 'get', params);
 }
 
 /**
  * 查询履约步骤枚举
  */
-export function queryWrPerformanceStepType(params: HttpRequest<{ rsp: Ermcp.WrPerformanceStepTypeRsp[] }>) {
+export function queryWrPerformanceStepType(params: HttpParams<{ rsp: Ermcp.WrPerformanceStepTypeRsp[] }>) {
     return httpRequest('/WrTrade2/QueryWrPerformanceStepType', 'get', params);
 }
 
 /**
  * 查询履约信息详情
  */
-export function queryWrPerformancePlanStep(params: HttpRequest<{ req: Ermcp.WrPerformancePlanStepReq, rsp: Ermcp.WrPerformancePlanStepRsp[] }>) {
+export function queryWrPerformancePlanStep(params: HttpParams<{ req: Ermcp.WrPerformancePlanStepReq, rsp: Ermcp.WrPerformancePlanStepRsp[] }>) {
     return httpRequest('/WrTrade2/QueryWrPerformancePlanStep', 'get', params);
 }

+ 3 - 3
src/services/api/quote/index.ts

@@ -1,16 +1,16 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 
 /**
  * 历史行情
  */
-export function queryHistoryDatas(params: HttpRequest<{ req: { goodscode?: string }, rsp: Ermcp.QueryHistoryDatasRsp[] }>) {
+export function queryHistoryDatas(params: HttpParams<{ req: { goodscode?: string }, rsp: Ermcp.QueryHistoryDatasRsp[] }>) {
     return httpRequest('/Quote/QueryHistoryDatas', 'get', params);
 }
 
 /**
  * 历史行情
  */
-export function queryTSData(params: HttpRequest<{ req: { goodscode?: string }, rsp: Ermcp.QueryTSDataRsp }>) {
+export function queryTSData(params: HttpParams<{ req: { goodscode?: string }, rsp: Ermcp.QueryTSDataRsp }>) {
     return httpRequest('/Quote/QueryTSData', 'get', params);
 }

+ 18 - 18
src/services/api/trade/index.ts

@@ -1,117 +1,117 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 import { Market } from '@/constants/market'
 
 /**
  * 钻石买挂牌
  */
-export function zsBuyOrderListing(params: TradeRequest<Proto.ZSBuyOrderListingReq, Proto.ZSBuyOrderListingRsp>) {
+export function zsBuyOrderListing(params: TradeParams<Proto.ZSBuyOrderListingReq, Proto.ZSBuyOrderListingRsp>) {
     return tradeServerRequest('ZSBuyOrderListingReq', 'ZSBuyOrderListingRsp', params, Market.GZ);
 }
 
 /**
  * 钻石卖挂牌
  */
-export function zsSellOrderListing(params: TradeRequest<Proto.ZSSellOrderListingReq, Proto.ZSSellOrderListingRsp>) {
+export function zsSellOrderListing(params: TradeParams<Proto.ZSSellOrderListingReq, Proto.ZSSellOrderListingRsp>) {
     return tradeServerRequest('ZSSellOrderListingReq', 'ZSSellOrderListingRsp', params, Market.GZ);
 }
 
 /**
  * 钻石买摘牌
  */
-export function zsBuyOrderDesting(params: TradeRequest<Proto.ZSBuyOrderDestingReq, Proto.ZSBuyOrderDestingRsp>) {
+export function zsBuyOrderDesting(params: TradeParams<Proto.ZSBuyOrderDestingReq, Proto.ZSBuyOrderDestingRsp>) {
     return tradeServerRequest('ZSBuyOrderDestingReq', 'ZSBuyOrderDestingRsp', params, Market.GZ);
 }
 
 /**
  * 钻石买摘牌询价
  */
-export function zsBuyOrderDestingNegPrice(params: TradeRequest<Proto.ZSBuyOrderDestingNegPriceReq, Proto.ZSBuyOrderDestingNegPriceRsp>) {
+export function zsBuyOrderDestingNegPrice(params: TradeParams<Proto.ZSBuyOrderDestingNegPriceReq, Proto.ZSBuyOrderDestingNegPriceRsp>) {
     return tradeServerRequest('ZSBuyOrderDestingNegPriceReq', 'ZSBuyOrderDestingNegPriceRsp', params, Market.GZ);
 }
 
 /**
  * 钻石卖摘牌申请
  */
-export function zsSellOrderDestingApply(params: TradeRequest<Proto.ZSSellOrderDestingApplyReq, Proto.ZSSellOrderDestingApplyRsp>) {
+export function zsSellOrderDestingApply(params: TradeParams<Proto.ZSSellOrderDestingApplyReq, Proto.ZSSellOrderDestingApplyRsp>) {
     return tradeServerRequest('ZSSellOrderDestingApplyReq', 'ZSSellOrderDestingApplyRsp', params, Market.GZ);
 }
 
 /**
  * 钻石买询价操作
  */
-export function zsBuyOrderDestingNegPriceOperate(params: TradeRequest<Proto.ZSBuyOrderDestingNegPriceOperateReq, Proto.ZSBuyOrderDestingNegPriceOperateRsp>) {
+export function zsBuyOrderDestingNegPriceOperate(params: TradeParams<Proto.ZSBuyOrderDestingNegPriceOperateReq, Proto.ZSBuyOrderDestingNegPriceOperateRsp>) {
     return tradeServerRequest('ZSBuyOrderDestingNegPriceOperateReq', 'ZSBuyOrderDestingNegPriceOperateRsp', params, Market.GZ);
 }
 
 /**
  * 钻石卖询价操作
  */
-export function zsSellOrderDestingApplyOperate(params: TradeRequest<Proto.ZSSellOrderDestingApplyOperateReq, Proto.ZSSellOrderDestingApplyOperateRsp>) {
+export function zsSellOrderDestingApplyOperate(params: TradeParams<Proto.ZSSellOrderDestingApplyOperateReq, Proto.ZSSellOrderDestingApplyOperateRsp>) {
     return tradeServerRequest('ZSSellOrderDestingApplyOperateReq', 'ZSSellOrderDestingApplyOperateRsp', params, Market.GZ);
 }
 
 /**
  * 钻石挂牌撤单
  */
-export function wrListingCancelOrder(params: TradeRequest<Proto.WRListingCancelOrderReq, Proto.WRListingCancelOrderRsp>) {
+export function wrListingCancelOrder(params: TradeParams<Proto.WRListingCancelOrderReq, Proto.WRListingCancelOrderRsp>) {
     return tradeServerRequest('WRListingCancelOrderReq', 'WRListingCancelOrderRsp', params, Market.GZ);
 }
 
 /**
  * 查询求购大厅委托单
  */
-export function queryBuyOrder(params: HttpRequest<{ req: Ermcp.BuyOrderReq, rsp: Ermcp.BuyOrderRsp[] }>) {
+export function queryBuyOrder(params: HttpParams<{ req: Ermcp.BuyOrderReq, rsp: Ermcp.BuyOrderRsp[] }>) {
     return httpRequest('/Guangzuan/QueryBuyOrder', 'get', params);
 }
 
 /**
  * 查询我的求购
  */
-export function queryMyBuyOrder(params: HttpRequest<{ req: Ermcp.MyBuyOrderReq, rsp: Ermcp.MyBuyOrderRsp[] }>) {
+export function queryMyBuyOrder(params: HttpParams<{ req: Ermcp.MyBuyOrderReq, rsp: Ermcp.MyBuyOrderRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyBuyOrder', 'get', params);
 }
 
 /**
  * 搜索出售大厅委托单
  */
-export function searchSellOrder(params: HttpRequest<{ req: Ermcp.SellOrderSearchReq, rsp: Ermcp.SellOrderSearchRsp[] }>) {
+export function searchSellOrder(params: HttpParams<{ req: Ermcp.SellOrderSearchReq, rsp: Ermcp.SellOrderSearchRsp[] }>) {
     return httpRequest('/Guangzuan/QueryDiamond', 'post', params);
 }
 
 /**
  * 查询出售大厅委托单
  */
-export function querySellOrder(params: HttpRequest<{ req: Ermcp.SellOrderReq, rsp: Ermcp.SellOrderRsp[] }>) {
+export function querySellOrder(params: HttpParams<{ req: Ermcp.SellOrderReq, rsp: Ermcp.SellOrderRsp[] }>) {
     return httpRequest('/Guangzuan/QuerySellOrder', 'get', params);
 }
 
 /**
  * 查询我的出售
  */
-export function queryMySellOrder(params: HttpRequest<{ req: Ermcp.MySellOrderReq, rsp: Ermcp.MySellOrderRsp[] }>) {
+export function queryMySellOrder(params: HttpParams<{ req: Ermcp.MySellOrderReq, rsp: Ermcp.MySellOrderRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMySellOrder', 'get', params);
 }
 
 /**
  * 查询我的摘牌
  */
-export function queryMyDeListing(params: HttpRequest<{ req: Ermcp.MyDeListingReq, rsp: Ermcp.MyDeListingRsp[] }>) {
+export function queryMyDeListing(params: HttpParams<{ req: Ermcp.MyDeListingReq, rsp: Ermcp.MyDeListingRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyDeListing', 'get', params);
 }
 
 /**
  * 查询询价-求购
  */
-export function queryMyBargainApply(params: HttpRequest<{ req: Ermcp.MyBargainApplyReq, rsp: Ermcp.MyBargainApplyRsp[] }>) {
+export function queryMyBargainApply(params: HttpParams<{ req: Ermcp.MyBargainApplyReq, rsp: Ermcp.MyBargainApplyRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyBargainApply', 'get', params);
 }
 
 /**
  * 查询询价-出售
  */
-export function queryMyDelistingApply(params: HttpRequest<{ req: Ermcp.MyDelistingApplyReq, rsp: Ermcp.MyDelistingApplyRsp[] }>) {
+export function queryMyDelistingApply(params: HttpParams<{ req: Ermcp.MyDelistingApplyReq, rsp: Ermcp.MyDelistingApplyRsp[] }>) {
     return httpRequest('/Guangzuan/QueryMyDelistingApply', 'get', params);
 }

+ 9 - 9
src/services/api/user/index.ts

@@ -1,53 +1,53 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 
 /**
  * 查询收货地址信息
  */
-export function queryUserReceiveInfo(params: HttpRequest<{ req: Ermcp.UserReceiveInfoReq, rsp: Ermcp.UserReceiveInfoRsp[] }>) {
+export function queryUserReceiveInfo(params: HttpParams<{ req: Ermcp.UserReceiveInfoReq, rsp: Ermcp.UserReceiveInfoRsp[] }>) {
     return httpRequest('/Qhj/QueryUserReceiveInfo', 'get', params);
 }
 
 /**
  * 查询发票信息
  */
-export function queryWrUserReceiptInfo(params: HttpRequest<{ req: Ermcp.WrUserReceiptInfoReq, rsp: Ermcp.WrUserReceiptInfoRsp[] }>) {
+export function queryWrUserReceiptInfo(params: HttpParams<{ req: Ermcp.WrUserReceiptInfoReq, rsp: Ermcp.WrUserReceiptInfoRsp[] }>) {
     return httpRequest('/WrTrade2/QueryWrUserReceiptInfo', 'get', params);
 }
 
 /**
  * 新增修改收货地址
  */
-export function userReceiveInfo(params: TradeRequest<Proto.UserReceiveInfoReq, Proto.UserReceiveInfoRsp>) {
+export function userReceiveInfo(params: TradeParams<Proto.UserReceiveInfoReq, Proto.UserReceiveInfoRsp>) {
     return tradeServerRequest('UserReceiveInfoReq', 'UserReceiveInfoRsp', params);
 }
 
 /**
  * 删除收货地址
  */
-export function delUserReceiveInfo(params: TradeRequest<Proto.DelUserReceiveInfoReq, Proto.DelUserReceiveInfoRsp>) {
+export function delUserReceiveInfo(params: TradeParams<Proto.DelUserReceiveInfoReq, Proto.DelUserReceiveInfoRsp>) {
     return tradeServerRequest('DelUserReceiveInfoReq', 'DelUserReceiveInfoRsp', params);
 }
 
 /**
  * 设置默认收货地址
  */
-export function userReceiveIsDefault(params: TradeRequest<Proto.UserReceiveIsDefaultReq, Proto.UserReceiveIsDefaultRsp>) {
+export function userReceiveIsDefault(params: TradeParams<Proto.UserReceiveIsDefaultReq, Proto.UserReceiveIsDefaultRsp>) {
     return tradeServerRequest('UserReceiveIsDefaultReq', 'UserReceiveIsDefaultRsp', params);
 }
 
 /**
  * 新增修改用户发票信息
  */
-export function userReceiptInfo(params: TradeRequest<Proto.UserReceiptInfoReq, Proto.UserReceiptInfoRsp>) {
+export function userReceiptInfo(params: TradeParams<Proto.UserReceiptInfoReq, Proto.UserReceiptInfoRsp>) {
     return tradeServerRequest('UserReceiptInfoReq', 'UserReceiptInfoRsp', params);
 }
 
 /**
  * 删除用户发票信息
  */
-export function delUserReceiptInfo(params: TradeRequest<Proto.DelUserReceiptInfoReq, Proto.DelUserReceiptInfoRsp>) {
+export function delUserReceiptInfo(params: TradeParams<Proto.DelUserReceiptInfoReq, Proto.DelUserReceiptInfoRsp>) {
     return tradeServerRequest('DelUserReceiptInfoReq', 'DelUserReceiptInfoRsp', params);
 }

+ 4 - 4
src/services/api/warehouse/index.ts

@@ -1,18 +1,18 @@
 import { httpRequest } from '@/services/http'
-import { HttpRequest } from '@/services/http/interface'
+import { HttpParams } from '@/services/http/interface'
 import { tradeServerRequest } from '@/services/socket/trade'
-import { TradeRequest } from '@/services/socket/trade/interface'
+import { TradeParams } from '@/services/socket/trade/interface'
 
 /**
  * 查询仓库信息
  */
-export function queryWarehouseInfo(params: HttpRequest<{ req: Ermcp.WarehouseInfoReq, rsp: Ermcp.WarehouseInfoRsp[] }>) {
+export function queryWarehouseInfo(params: HttpParams<{ req: Ermcp.WarehouseInfoReq, rsp: Ermcp.WarehouseInfoRsp[] }>) {
     return httpRequest('/Guangzuan/QueryWarehouseInfo', 'get', params);
 }
 
 /**
  * 仓库新增修改
  */
-export function warehouseApply(params: TradeRequest<Proto.WarehouseApplyReq, Proto.WarehouseApplyRsp>) {
+export function warehouseApply(params: TradeParams<Proto.WarehouseApplyReq, Proto.WarehouseApplyRsp>) {
     return tradeServerRequest('WarehouseApplyReq', 'WarehouseApplyRsp', params);
 }

+ 119 - 83
src/services/http/index.ts

@@ -1,102 +1,138 @@
-import axios, { AxiosRequestConfig, Method } from 'axios'
+import axios, { AxiosRequestConfig, Method, AxiosInstance } from 'axios'
 //import qs from 'qs'
 //import cryptojs from 'crypto-js'
 //import { addPending, removePending } from './pending'
 import { useLoginStore } from '@/stores'
-import { HttpRequest, HttpResponse, ResultCode } from './interface'
+import { HttpParams, CommonParams, HttpResponse, Payload, ResultCode } from './interface'
 import service from '@/services'
 
-const http = axios.create({
-    timeout: 30000,
-})
+const httpService = new (class {
+    private axiosInstance?: AxiosInstance
 
-/**
- * 请求拦截器
- */
-http.interceptors.request.use(
-    (config) => {
-        const { getToken } = useLoginStore();
-        //removePending(config); //在请求开始前,对之前的请求做检查取消操作
-        //addPending(config); //将当前请求添加到列表中
+    constructor() {
+        this.init()
+    }
 
-        //请求头签名
-        const sign = {
-            token: getToken(),
-            signsecret: 'qz7qWOMXKTMT5JlDs5w4NTPwWeR3xhF1v6wqbZ9cExmP6cc3spvNAp1wJJ1SqRI5',
-            timestamp: new Date().getTime(),
-        };
-        //设置请求头
-        config.headers = {
-            Authorization: sign.token,
-            //Signid: 'eecd3f37625f4501b88e9f0fa14b4b51',
-            //Sign: cryptojs.SHA256(qs.stringify(sign)).toString(),
-            //Timestamp: sign.timestamp.toString(),
-        };
+    private init = async () => {
+        if (!this.axiosInstance) {
+            const config = await service.onReady()
+            this.axiosInstance = axios.create({
+                timeout: 30000,
+                baseURL: config.goCommonSearchUrl,
+            })
+            // 请求拦截器
+            this.axiosInstance.interceptors.request.use(
+                (config) => {
+                    const { getToken } = useLoginStore()
+                    //removePending(config) //在请求开始前,对之前的请求做检查取消操作
+                    //addPending(config) //将当前请求添加到列表中
 
-        return config;
-    },
-    (err) => {
-        //此处异常触发条件不明
-        console.error(err);
-        return Promise.reject('网络异常,请稍后再试');
-    }
-)
+                    //请求头签名
+                    const sign = {
+                        token: getToken(),
+                        signsecret: 'qz7qWOMXKTMT5JlDs5w4NTPwWeR3xhF1v6wqbZ9cExmP6cc3spvNAp1wJJ1SqRI5',
+                        timestamp: new Date().getTime(),
+                    }
+                    //设置请求头
+                    config.headers = {
+                        Authorization: sign.token,
+                        //Signid: 'eecd3f37625f4501b88e9f0fa14b4b51',
+                        //Sign: cryptojs.SHA256(qs.stringify(sign)).toString(),
+                        //Timestamp: sign.timestamp.toString(),
+                    }
 
-/**
- * 响应拦截器
- */
-http.interceptors.response.use(
-    (res) => {
-        //removePending(res); //在请求结束后,移除本次请求
-        return res;
-    },
-    (err) => {
-        if (!axios.isCancel(err)) {
-            console.error(err);
+                    return config
+                },
+                (err) => {
+                    //此处异常触发条件不明
+                    console.error(err)
+                    return Promise.reject('网络异常,请稍后再试')
+                }
+            )
+            // 响应拦截器
+            this.axiosInstance.interceptors.response.use(
+                (res) => {
+                    //removePending(res) //在请求结束后,移除本次请求
+                    return res
+                },
+                (err) => {
+                    const { msg, message } = err.response.data
+                    if (!axios.isCancel(err)) {
+                        console.error(err)
+                    }
+                    // 异常提示待优化
+                    return Promise.reject(msg || message || '服务器异常,请稍后再试')
+                }
+            )
         }
-        // 异常提示待优化
-        return Promise.reject(err.response?.data.msg || '服务器异常,请稍后再试');
+        return Promise.resolve(this.axiosInstance)
     }
-)
 
-/**
- * Http请求
- */
-export async function httpRequest<T extends { req?: unknown, rsp?: unknown }>(url: string, method: Method, params: HttpRequest<T>) {
-    const { success, fail, complete } = params;
-    const { goCommonSearchUrl } = service.config;
+    private request = async (url: string, method: Method, params?: unknown) => {
+        const requestConfig: AxiosRequestConfig = {
+            url,
+            method,
+        }
+        if (params instanceof Object) {
+            if (['post', 'POST', 'put', 'PUT', 'patch', 'PATCH'].includes(method)) {
+                requestConfig.data = params
+            } else {
+                requestConfig.params = params
+            }
+        } else {
+            requestConfig.url = url + (params ?? '')
+        }
+        const instance = await this.init()
+        return instance(requestConfig)
+    }
 
-    const requestConfig: AxiosRequestConfig = {
-        url: goCommonSearchUrl + url,
-        method: method,
+    commonRequest = async <T extends Payload>(url: string, method: Method, params: CommonParams<T>) => {
+        const { data, success, fail, complete } = params
+        await this.request(url, method, data).then((res) => {
+            const data = res.data as T['rsp']
+            success && success(data)
+        }).catch((err) => {
+            fail && fail(err)
+            return Promise.reject(err)
+        }).finally(() => {
+            complete && complete()
+        })
     }
 
-    if (['post', 'POST', 'put', 'PUT', 'patch', 'PATCH'].includes(method)) {
-        requestConfig.data = params.data ?? {};
-    } else {
-        requestConfig.params = params.data ?? {};
+    httpRequest = async <T extends Payload>(url: string, method: Method, params: HttpParams<T>) => {
+        const { data, success, fail, complete } = params
+        await this.request(url, method, data).then((res) => {
+            const data = res.data as HttpResponse<T['rsp']>
+            switch (data.code) {
+                case ResultCode.InvalidToken:
+                    //退出登录
+                    //store.dispatch("user/logout", () => {
+                    //    window.location.reload()
+                    //})
+                    return Promise.reject('令牌无效')
+                case ResultCode.Success:
+                    success && success(data)
+                    return Promise.resolve()
+                default:
+                    fail && fail(data.msg)
+                    return Promise.reject(data.msg)
+            }
+        }).catch((err) => {
+            fail && fail(err)
+            return Promise.reject(err)
+        }).finally(() => {
+            complete && complete()
+        })
     }
+})
 
-    await http(requestConfig).then((res) => {
-        const data = res.data as HttpResponse<T['rsp']>;
-        switch (data.code) {
-            case ResultCode.InvalidToken:
-                //退出登录
-                //store.dispatch("user/logout", () => {
-                //    window.location.reload();
-                //});
-                return Promise.reject('令牌无效');
-            case ResultCode.Success:
-                success && success(data);
-                return Promise.resolve();
-            default:
-                fail && fail(data.msg);
-                return Promise.reject(data.msg);
-        }
-    }).catch((err) => {
-        fail && fail(err);
-        return Promise.reject(err);
-    }).finally(() => {
-        complete && complete();
-    })
+export const { commonRequest, httpRequest } = httpService
+
+/**
+ * 获取服务配置地址
+ * @param key 
+ * @returns 
+ */
+export function getServiceUrl(key: keyof typeof service.config) {
+    return service.config[key]
 }

+ 19 - 6
src/services/http/interface.ts

@@ -1,14 +1,29 @@
+export type Payload<T = unknown, R = unknown> = {
+    req?: T,
+    rsp?: R
+}
+
 /**
- * Http请求参数
+ * 请求参数
  */
-export interface HttpRequest<T extends { req?: unknown, rsp?: unknown } = object> {
-    data?: T['req'];
-    success?: (res: HttpResponse<T['rsp']>) => void;
+export interface RequestParams<T, R> {
+    data?: T;
+    success?: (res: R) => void;
     fail?: (err: string) => void;
     complete?: () => void;
 }
 
 /**
+ * Http请求参数
+ */
+export type HttpParams<T extends Payload = object> = RequestParams<T['req'], HttpResponse<T['rsp']>>
+
+/**
+ * Http请求参数
+ */
+export type CommonParams<T extends Payload = object> = RequestParams<T['req'], T['rsp']>
+
+/**
  * Http响应结果
  */
 export interface HttpResponse<T> {
@@ -16,8 +31,6 @@ export interface HttpResponse<T> {
     msg: string;
     total: number;
     data: T;
-    page: number;
-    pagesize: number;
 }
 
 /**

+ 18 - 24
src/services/index.ts

@@ -1,9 +1,8 @@
 import axios from 'axios'
-import { httpRequest } from './http'
 
 export default new (class {
     /** 应用配置信息 */
-    private appConfig = axios('./config/appconfig.json');
+    private appConfig = axios('./config/appconfig.json')
 
     /** 服务配置信息 */
     config = {
@@ -32,42 +31,37 @@ export default new (class {
     }
 
     /** 服务初始化完成状态 */
-    isReady = false;
+    isReady = false
 
     /** 等待服务初始化 */
-    private isPending = true;
+    private isPending = true
 
     /**
      * 尝试自动初始化,若断网或其它原因导致初始化失败,需手动初始化
      */
-    private tryInit = this.init();
+    private tryInit = this.init()
 
     /**
      * 初始化服务配置
      */
     private init(): Promise<typeof this.config> {
-        this.isPending = true;
+        this.isPending = true
         return new Promise((resolve, reject) => {
             this.appConfig.then((res) => {
-                const { apiUrl } = res.data;
+                const { apiUrl } = res.data
                 // 获取服务接口地址
-                httpRequest(apiUrl, 'get', {
-                    success: (res) => {
-                        console.log('服务配置信息', res.data);
-                        this.config = res.data as typeof this.config;
-                        this.isReady = true;
-                        resolve(this.config);
-                    },
-                    fail: () => {
-                        reject('获取服务配置地址失败');
-                    },
-                    complete: () => {
-                        this.isPending = false;
-                    }
+                axios(apiUrl).then((res) => {
+                    this.config = res.data.data
+                    this.isReady = true
+                    resolve(this.config)
+                }).catch(() => {
+                    reject('获取服务配置地址失败')
+                }).finally(() => {
+                    this.isPending = false
                 })
             }).catch(() => {
-                this.isPending = false;
-                reject('获取配置信息失败');
+                this.isPending = false
+                reject('获取配置信息失败')
             })
         })
     }
@@ -78,9 +72,9 @@ export default new (class {
     onReady() {
         // 初始化失败时重新初始化
         if (!this.isReady && !this.isPending) {
-            this.tryInit = this.init();
+            this.tryInit = this.init()
         }
         // 确保当前只有一个初始化实例
-        return this.tryInit;
+        return this.tryInit
     }
 })

+ 3 - 3
src/services/socket/trade/index.ts

@@ -4,7 +4,7 @@ import { FunCode } from '@/constants/funcode'
 import { useLoginStore } from '@/stores/modules/login'
 import { useErrorInfoStore } from '@/stores/modules/errorInfo'
 import { IMessageHead } from './protobuf/proto'
-import { TradeRequest, TradeResponse } from './interface'
+import { TradeParams, TradeResponse } from './interface'
 import Protobuf from './protobuf'
 import socket from '../index'
 
@@ -33,7 +33,7 @@ function getProtoHeader(funCode: keyof typeof FunCode, header?: IMessageHead, ma
  * @param rspKey 回调代码
  * @param marketId 市场ID
  */
-function tradeServerMiddleware<Req, Rsp>(reqKey: keyof typeof FunCode, rspKey: keyof typeof FunCode, params: TradeRequest<Req, Rsp>, marketId?: number): Promise<Rsp> {
+function tradeServerMiddleware<Req, Rsp>(reqKey: keyof typeof FunCode, rspKey: keyof typeof FunCode, params: TradeParams<Req, Rsp>, marketId?: number): Promise<Rsp> {
     params.data.Header = getProtoHeader(reqKey, params.data.Header, marketId);
     console.log(reqKey, FunCode[reqKey], params.data);
 
@@ -73,7 +73,7 @@ function tradeServerMiddleware<Req, Rsp>(reqKey: keyof typeof FunCode, rspKey: k
  * @param params 
  * @param marketId 
  */
-export async function tradeServerRequest<Req, Rsp>(reqKey: keyof typeof FunCode, rspKey: keyof typeof FunCode, params: TradeRequest<Req, Rsp & TradeResponse>, marketId?: number) {
+export async function tradeServerRequest<Req, Rsp>(reqKey: keyof typeof FunCode, rspKey: keyof typeof FunCode, params: TradeParams<Req, Rsp & TradeResponse>, marketId?: number) {
     const { getErrorInfoByCode } = useErrorInfoStore();
     const { success, fail, complete } = params;
 

+ 1 - 1
src/services/socket/trade/interface.ts

@@ -3,7 +3,7 @@ import { IMessageHead } from './protobuf/proto'
 /**
  * 交易服务请求参数
  */
-export interface TradeRequest<Req, Rsp> {
+export interface TradeParams<Req, Rsp> {
     data: { Header?: IMessageHead } & Req;
     success?: (res: Rsp) => void;
     fail?: (err: string) => void;

+ 20 - 25
src/stores/@next.ts

@@ -6,6 +6,7 @@ type Getters<T> = {
 
 interface Store<S extends object, G extends Getters<G>, A extends object, M extends object> {
     state: UnwrapNestedRefs<S>;
+    //getters: { [key in keyof G]: ComputedRef<ReturnType<G[key]>> };
     getters: G;
     actions: A;
     methods: M;
@@ -29,41 +30,35 @@ interface StoreOptions<S extends object, G extends Getters<G>, A extends object,
  */
 export function createStore<S extends object, G extends Getters<G>, A extends object, M extends object>(options: StoreOptions<S, G, A, M>) {
     const state = reactive(options.state())
-    const getters = options.getters
-    const actions = options.actions
-
-    const methods = {
-        $setData: (callback: (state: UnwrapNestedRefs<S>) => void) => {
-            callback(state)
-        },
-        $storeToRefs: () => {
-            return toRefs(state)
-        },
-        ...options.methods,
-    }
+    const getters = (options.getters ?? {}) as { [key in keyof G]: G[key] }
+    const actions = (options.actions ?? {}) as { [key in keyof A]: A[key] }
+    const methods = (options.methods ?? {}) as { [key in keyof M]: M[key] }
 
     const store = {
         state,
         getters,
         actions,
-        methods,
+        methods: {
+            $setData: (callback: (state: UnwrapNestedRefs<S>) => void) => {
+                callback(state)
+            },
+            $storeToRefs: () => {
+                return toRefs(state)
+            },
+            ...methods
+        },
     }
 
-    for (const p in actions) {
-        const fn = actions[p]
+    for (const key in actions) {
+        const fn = actions[key]
         if (fn instanceof Function) {
-            actions[p] = fn.bind(store)
+            actions[key] = fn.bind(store)
         }
     }
 
-    //options.created && options.created(store)
+    options.created && options.created(store)
 
-    return {
-        state,
-        getters,
-        actions,
-        methods,
-    }
+    return store
 }
 
 const store = createStore({
@@ -76,7 +71,7 @@ const store = createStore({
     getters: {
         getUserid() {
             return 10086
-        }
+        },
     },
     actions: {
         getAllEnumList(userid: number) {
@@ -89,7 +84,7 @@ const store = createStore({
     },
 })
 
-store.actions?.getAllEnumList(10086)
+store.actions.getAllEnumList(10086)
 
 setTimeout(() => {
     console.log(store.state)

+ 1 - 1
src/stores/modules/login.ts

@@ -85,7 +85,7 @@ const store = new (class extends VueStore<StoreState> {
         },
         /** 获取登录ID */
         getLoginId: () => {
-            return this.state.loginInfo.LoginID
+            return Number(this.state.loginInfo.LoginID)
         },
         /** 获取首个账户ID */
         getFirstAccountId: () => {

+ 35 - 26
src/types/ermcp/account.d.ts

@@ -180,32 +180,41 @@ declare global {
         }
 
         interface UserAccount {
-            accountname: string;//账户名称(机构名称)
-            accountstatus: number;//账户状态 - 1:待激活 2:待审核 3:待复审 4:正常 5:审核拒绝 6:注销
-            auditremark: string;//审核备注
-            audittime: string;//审核时间
-            audituserid: number;//审核人
-            broker: number;//所属经纪人ID
-            canceltime: string;//销户时间
-            canceluserid: number;//销户人
-            createtime: string;//创建时间
-            creatorid: number;//创建人
-            hasauth: number;//是否已实名认证 - 0:未认证 1:已认证 2:已提交(待审核) 3:已拒绝
-            isanonymous: number;//是否匿名下单 - 0:否 1:是
-            maxinvestornum: number;//最大用户数(经纪会员下投资者个数)
-            memberuserid: number;//所属会员ID
-            modifierid: number;//修改人
-            modifyremark: string;//变更备注
-            modifystatus: number;//变更状态 1 未变更 2 变更中 3 变更待审核 4 变更待复核(投资者)
-            modifytime: string;//修改时间
-            parentuserid: number;//所属机构ID
-            reckonaccountid: number;//默认结算资金账号ID(机构分润使用) 作废
-            refercount: number;//推荐总人数
-            refereeuserid: number;//推荐人ID
-            refernum: string;//推荐码
-            subarealevelpath: string;//子机构层级路径(逗号分隔,首尾加逗号)
-            userid: number;//用户ID
-            usertype: number;//账户类型 - 1:交易所 2:机构 3:会员子机构 4:经纪人 5:投资者 6:客户
+            accountname: string; // 账户名称(机构名称)
+            accountstatus: number; // 账户状态 - 1:待激活 2:待审核 3:待复审 4:正常 5:审核拒绝 6:停用(注销) 7:注销(删除)
+            applysrc: number; // 申请来源 - 1:管理端 2:终端
+            auditremark: string; // 审核备注
+            auditsrc: number; // 审核来源 - 1:管理端 2:终端
+            audittime: string; // 审核时间
+            audituserid: number; // 审核人
+            broker: number; // 所属经纪人ID
+            canceltime: string; // 销户时间
+            canceluserid: number; // 销户人
+            canrecommend: number; // 是否可推荐 - 0:不可 1;可
+            createtime: string; // 创建时间
+            creatorid: number; // 创建人
+            curscore: number; // 积分
+            hasauth: number; // 是否已实名认证 - 0:未认证 1:已认证 2:已提交(待审核) 3:已拒绝
+            isanonymous: number; // 是否匿名下单 - 0:否 1:是
+            issigned: boolean; // 今日是否已签到
+            maxinvestornum: number; // 最大用户数(经纪会员下投资者个数)
+            memberuserid: number; // 所属会员ID
+            modifierid: number; // 修改人
+            modifyremark: string; // 变更备注
+            modifystatus: number; // 变更状态 1 未变更 2 变更中 3 变更待审核 4 变更待复核(投资者)
+            modifytime: string; // 修改时间
+            parenttopuser: string; // 上级顶级机构 [092=0,1时,默认为1, 092=2时若自已为顶级,则填入自己,自己不为顶级,填入ParentUserID的"ParentTopUser"]
+            parentuserid: number; // 所属机构ID
+            reckonaccountid: number; // 默认结算资金账号ID(机构分润使用) 作废
+            refercount: number; // 推荐总人数
+            refereeuserid: number; // 推荐人ID
+            refernum: string; // 推荐码
+            rootuserid: number; // 根用户ID
+            subaccountlevel: number; // 子账户层数
+            subarealevelpath: string; //子机构层级路径(逗号分隔,首尾加逗号)
+            todayrefercount: number; // 今日推荐人数
+            userid: number; // 用户ID
+            usertype: number; // 账户类型 - 1:交易所 2:机构 3:会员子机构 4:经纪人 5:投资者 6:客户 7:企业成员(云平台)
         }
 
         interface UserInfo {

+ 1 - 0
src/types/ermcp/trade.d.ts

@@ -343,6 +343,7 @@ declare namespace Ermcp {
         size1: string;
         size2: string;
         size3: string;
+        sizedisplay: string; // 尺寸
         stonedesc: string;
         totalqty: number; // 总重量
         tradedate: string; // 交易日(yyyyMMdd)