فهرست منبع

feat: 新增日志模块

tangning 2 سال پیش
والد
کامیت
d0895c67a5

+ 13 - 1
src/api/equity/index.ts

@@ -9,7 +9,8 @@ enum Api {
   listApi = '/service/agent/increment/list',
   allList = '/service/agent/incrementType/allList',
   addDowm = '/service/agent/down/add',
-  dowmList = '/service/agent/down/list'
+  dowmList = '/service/agent/down/list',
+  cameraIncrementLog = '/service/agent/cameraIncrementLog/list'
 }
 
 export const listApi = (params:listParams) =>
@@ -87,3 +88,14 @@ export const addDowm = (params:checkParams) =>
         ignoreCancelToken: true,
       },
 });
+
+export const cameraIncrementLog = (params:checkParams) =>
+    defHttp.post<Result>({
+      url: Api.cameraIncrementLog,
+      params: params,
+      // data: params,
+      headers: {
+        // @ts-ignore
+        ignoreCancelToken: true,
+      },
+});

BIN
src/assets/images/grey-logo-en.png


+ 6 - 2
src/components/Application/src/AppLogo.vue

@@ -4,7 +4,7 @@
 -->
 <template>
   <div class="anticon" :class="getAppLogoClass" @click="goHome">
-    <img src="../../../assets/images/grey-logo.png" />
+    <img :src="isEn?logoEn:logo" />
     <!-- <div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
       {{ title }}
     </div> -->
@@ -18,6 +18,9 @@
   import { useDesign } from '/@/hooks/web/useDesign';
   import { PageEnum } from '/@/enums/pageEnum';
   import { useUserStore } from '/@/store/modules/user';
+  import { useLocaleStore } from '/@/store/modules/locale';
+  import logo from '/@/assets/images/grey-logo.png';
+  import logoEn from '/@/assets/images/grey-logo-en.png';
 
   const props = defineProps({
     /**
@@ -33,7 +36,8 @@
      */
     alwaysShowTitle: { type: Boolean },
   });
-
+  const localeStore = useLocaleStore();
+  const isEn = computed(() => localeStore.getLocale === 'en');
   const { prefixCls } = useDesign('app-logo');
   const { getCollapsedShowTitle } = useMenuSetting();
   const userStore = useUserStore();

+ 0 - 6
src/components/Form/src/components/FormItem.vue

@@ -245,12 +245,6 @@
             const target = e ? e.target : null;
             const value = target ? (isCheck ? target.checked : target.value) : e;
             props.setFormModel(field, value);
-            // 这个也要添加
-            // 这个也要添加
-            props.validateFields([field], { triggerName: 'change' }).catch(() => {});
-            },
-            onBlur: () => {
-            props.validateFields([field], { triggerName: 'blur' }).catch(() => {});
           },
         };
         const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>;

+ 1 - 0
src/locales/lang/en/routes/dashboard.ts

@@ -8,4 +8,5 @@ export default {
   scene:'Scene Management',
   finance:'Sales Statistics',
   cameraScene: 'Scene Management',
+  loglist:'Operation Log',
 };

+ 8 - 0
src/locales/lang/en/routes/device.ts

@@ -13,5 +13,13 @@ export default {
     9:'4DMinion',
     10:'4DMega',
   },
+  status:{
+    0:'Active',
+    1:'Expired',
+    2:'Bound',
+    3:'Unbound',
+  },
+  bindStatus:'Binding status',
+  statusName:'Status'
 }
 

+ 11 - 0
src/locales/lang/en/routes/equity.ts

@@ -56,6 +56,17 @@ export default {
     1:'Statistical Guidelines:',
     2:'Membership Subscription: current records of new authorizations by dealers and related ID renewal records, including dealer authorizations and renewals, platform authorizations (renewals), and official website purchases (renewals).',
     3:'Scene Download: statistical information on the number of downloads of current new authorizations by sales.',
+  },
+  totalTime:'End Date',
+  totalMessge:'Insufficient Remaining Saleable Membership Subscriptions',
+  operationType:'Type',
+  operationUserName:'User',
+  operationTime:'Operation Time',
+  incrementId:'Membership Subscription ID',
+  platform: 'Platform',
+  operation:{
+    0:'Authorize',
+    1:'Unbind',
   }
 }
 

+ 1 - 0
src/locales/lang/en/routes/finance.ts

@@ -22,4 +22,5 @@ export default {
     2: 'Official Website Purchase',
     3: 'Platform Authorization',
   },
+  totalTime:'Total duration of the authorization (year/month)',
 };

+ 1 - 0
src/locales/lang/zh-CN/routes/dashboard.ts

@@ -67,4 +67,5 @@ export default {
   equity:'权益管理',
   scene:'场景管理',
   finance:'销售统计',
+  loglist:'权益操作日志',
 };

+ 8 - 0
src/locales/lang/zh-CN/routes/device.ts

@@ -13,4 +13,12 @@ export default {
     9:'四维看见',
     10:'四维深时',
   },
+  status:{
+    0:'生效中',
+    1:'已过期',
+    2:'已绑定',
+    3:'未绑定',
+  },
+  bindStatus:'绑定状态',
+  statusName:'权益状态'
 }

+ 11 - 0
src/locales/lang/zh-CN/routes/equity.ts

@@ -56,6 +56,17 @@ export default {
     1:'统计规则:',
     2:'1、会员权益:统计当前经销商新授权的记录、以及相关权益ID续费记录,包括经销商授权和续费、平台授权(续费)、官网自购(续费);',
     3:'2、场景下载:统计当前经销售新授权(除相关用户)的下载次数;',
+  },
+  totalTime:'期限',
+  totalMessge:'剩余可售权益不足',
+  operationType:'操作类型',
+  operationUserName:'操作用户',
+  operationTime:'操作时间',
+  incrementId:'权益ID',
+  platform: '平台',
+  operation:{
+    0:'授权',
+    1:'解除',
   }
 }
 

+ 1 - 0
src/locales/lang/zh-CN/routes/finance.ts

@@ -22,4 +22,5 @@ export default {
     2: '官网自购',
     3: '平台授权',
   },
+  totalTime:'授权总期限(年/月)',
 };

+ 1 - 1
src/router/routes/modules/equity.ts

@@ -10,7 +10,7 @@ export const equityRoute: AppRouteRecordRaw = {
   meta: {
     title: t('routes.dashboard.equity'),
     icon: 'raphael:customer',
-    orderNo: 5,
+    orderNo: 8,
     hideChildrenInMenu: true,
   },
   children: [

+ 28 - 0
src/router/routes/modules/loglist.ts

@@ -0,0 +1,28 @@
+import type { AppRouteRecordRaw } from '/@/router/types';
+import { t } from '/@/hooks/web/useI18n';
+import { LAYOUT } from '/@/router/constant';
+
+export const LoglistRoute: AppRouteRecordRaw = {
+  path: '/loglist',
+  name: 'Loglist',
+  redirect: '/loglist/index',
+  component: LAYOUT,
+  meta: {
+    title: t('routes.dashboard.loglist'),
+    icon: 'ic:baseline-receipt-long',
+    orderNo: 11,
+    hideChildrenInMenu: true,
+  },
+  children: [
+    {
+      path: 'index',
+      name: 'LogListIndex',
+      component: () => import('/@/views/loglist/index.vue'),
+      meta: {
+        title: t('routes.dashboard.loglist'),
+        hideBreadcrumb: true,
+      },
+    },
+  ],
+};
+export default LoglistRoute;

+ 1 - 1
src/router/routes/modules/scene.ts

@@ -10,7 +10,7 @@ export const SceneRoute: AppRouteRecordRaw = {
   meta: {
     title: t('routes.dashboard.scene'),
     icon: 'carbon:carbon-for-ibm-product',
-    orderNo: 8,
+    orderNo: 5,
     hideChildrenInMenu: true,
   },
   children: [

+ 272 - 181
src/views/device/index.vue

@@ -1,213 +1,304 @@
 <template>
   <PageWrapper contentBackground>
     <div class="desc-wrap-BasicTable">
-      <BasicTable @register="registerTable">
-      </BasicTable>
+      <BasicTable @register="registerTable"> </BasicTable>
     </div>
   </PageWrapper>
 </template>
 <script lang="ts">
-  import { defineComponent, h, onMounted, computed } from 'vue';
-  import {
+import { defineComponent, h, onMounted, computed } from 'vue';
+import {
+  BasicTable,
+  useTable,
+  TableAction,
+  BasicColumn,
+  TableImg,
+  FormProps,
+} from '/@/components/Table';
+import { PageWrapper } from '/@/components/Page';
+import { Descriptions } from 'ant-design-vue';
+import { useI18n } from '/@/hooks/web/useI18n';
+import { useMessage } from '/@/hooks/web/useMessage';
+import { cameraList } from '/@/api/customer';
+import { cameraDelete } from '/@/api/device';
+import { useRouter } from 'vue-router';
+import { UnbindCameraApi } from '/@/api/account';
+import { usePermissionStore } from '/@/store/modules/permission';
+import { useLocaleStore } from '/@/store/modules/locale';
+import { dincrementList } from '/@/api/equity';
+export default defineComponent({
+  components: {
     BasicTable,
-    useTable,
     TableAction,
-    BasicColumn,
+    PageWrapper,
     TableImg,
-    FormProps,
-  } from '/@/components/Table';
-  import { PageWrapper } from '/@/components/Page';
-  import { Descriptions } from 'ant-design-vue';
-  import { useI18n } from '/@/hooks/web/useI18n';
-  import { useMessage } from '/@/hooks/web/useMessage';
-  import { cameraList } from '/@/api/customer';
-  import { cameraDelete } from '/@/api/device';
-  import { useRouter } from 'vue-router';
-  import { UnbindCameraApi } from '/@/api/account';
-  import { usePermissionStore } from '/@/store/modules/permission';
-  import { useLocaleStore } from '/@/store/modules/locale';
-  export default defineComponent({
-    components: {
-      BasicTable,
-      TableAction,
-      PageWrapper,
-      TableImg,
-      [Descriptions.name]: Descriptions,
-      [Descriptions.Item.name]: Descriptions.Item,
-    },
-    setup() {
-      const { t } = useI18n();
-      const { createMessage, createConfirm } = useMessage();
-      const permissionStore = usePermissionStore();
-      const { getCheckPerm } = permissionStore;
-      const router = useRouter();
-      const localeStore = useLocaleStore();
-      const isEn = computed(() => localeStore.getLocale === 'en');
-      const companyId: Number = router.currentRoute.value.params.id - 0;
-      onMounted(() => {
-        // console.log(router.currentRoute.value.params.id);
-      });
-      const columns: BasicColumn[] = [
-        {
-          title: t('routes.device.snCode'),
-          dataIndex: 'snCode',
-          width: 180,
+    [Descriptions.name]: Descriptions,
+    [Descriptions.Item.name]: Descriptions.Item,
+  },
+  setup() {
+    const { t } = useI18n();
+    const { createMessage, createConfirm } = useMessage();
+    const permissionStore = usePermissionStore();
+    const { getCheckPerm } = permissionStore;
+    const router = useRouter();
+    const localeStore = useLocaleStore();
+    const isEn = computed(() => localeStore.getLocale === 'en');
+    const companyId: Number = router.currentRoute.value.params.id - 0;
+    onMounted(() => {
+      // console.log(router.currentRoute.value.params.id);
+    });
+    const columns: BasicColumn[] = [
+      {
+        title: t('routes.device.snCode'),
+        dataIndex: 'snCode',
+        width: 180,
+      },
+      {
+        title: t('routes.device.wifiName'),
+        dataIndex: 'wifiName',
+        width: 150,
+      },
+      {
+        title: t('routes.device.deviceType'),
+        dataIndex: 'type',
+        ellipsis: false,
+        width: 80,
+        customRender: ({ record }) => {
+          let typeObj = {
+            '0': t('routes.device.type.0'),
+            '1': t('routes.device.type.1'),
+            '2': t('routes.device.type.2'),
+            '9': t('routes.device.type.9'),
+            '10': t('routes.device.type.10'),
+          };
+          return typeObj[record.type];
         },
-        {
-          title: t('routes.device.wifiName'),
-          dataIndex: 'wifiName',
-          width: 150,
+      },
+
+      {
+        title: t('routes.device.activatedTime'),
+        dataIndex: 'activatedTime',
+        width: 180,
+      },
+      {
+        title: t('routes.equity.Type'),
+        dataIndex: 'validTimeType',
+        width: 180,
+        customRender({ record }) {
+          return record.validTimeType==0 ?t('routes.equity.equityType.0'):record.validTimeType==1? t('routes.equity.equityType.3') : t('routes.device.NoBind');
         },
-        {
-          title: t('routes.device.deviceType'),
-          dataIndex: 'type',
-          ellipsis: false,
-          width: 80,  
-          customRender: ({ record }) => {
-            let typeObj ={
-              '0':t('routes.device.type.0'),
-              '1':t('routes.device.type.1'),
-              '2':t('routes.device.type.2'),
-              '9':t('routes.device.type.9'),
-              '10':t('routes.device.type.10'),
-            }
-            return typeObj[record.type]
-          }        
+      },
+      {
+        title: t('routes.device.statusName'),
+        dataIndex: 'incrementStatus',
+        customRender({ record }) {
+          if(record.incrementStatus == -1){
+            return '-'
+          }else{
+            return record.incrementStatus==0? t('routes.device.status.0') : t('routes.device.status.1');
+          }
         },
-
-        {
-          title: t('routes.device.activatedTime'),
-          dataIndex: 'activatedTime',
-          width: 180,
+        width: 180,
+      },
+      {
+        title: t('routes.device.userName'),
+        dataIndex: 'userName',
+        width: 180,
+        customRender({ record }) {
+          return record.userName ? record.userName : '-';
         },
+      },
+    ];
+    const searchForm: Partial<FormProps> = {
+      labelWidth: 120,
+      autoAdvancedLine:1,
+      actionColOptions: {
+        span: 24,
+      },
+      schemas: [
         {
-          title: t('routes.device.userName'),
-          dataIndex: 'userName',
-          width: 180,
-          customRender({ record }) {
-            return record.userName?record.userName:'-'
+          field: 'snCode',
+          component: 'Input',
+          label: t('routes.device.snCode'),
+          colProps: {
+            xl: 8,
+            xxl: 8,
           },
         },
-      ];
-      const searchForm: Partial<FormProps> = {
-        labelWidth: isEn.value?120:80,
-        autoAdvancedLine:1,
-        actionColOptions: {
-          span: 24,
-        },
-        schemas: [
-          {
-            field: 'snCode',
-            component: 'Input',
-            label: t('routes.device.snCode'),
-            colProps: {
-              xl: 6,
-              xxl: 6,
-            },
-          },{
-            field: 'type',
-            component: 'Select',
-            label: t('routes.device.deviceType'),
-            colProps: {
-              xl: 6,
-              xxl: 6,
-            },
-            componentProps: {
-              options: [
-                {
+        {
+          field: 'type',
+          component: 'Select',
+          label: t('routes.device.deviceType'),
+          colProps: {
+            xl: 8,
+            xxl: 8,
+          },
+          componentProps: {
+            options: [
+              {
                 //   label: t('routes.device.type.0'),
                 //   value: 0,
                 //   key: '0',
                 // },{
-                  label: t('routes.device.type.1'),
-                  value: 1,
-                  key: '1',
-                },{
-                  label: t('routes.device.type.2'),
-                  value: 9,
-                  key: '9',
-                },{
-                  label: t('routes.device.type.3'),
-                  value: 10,
-                  key: '10',
-                },
-              ],
-            },
+                label: t('routes.device.type.1'),
+                value: 1,
+                key: '1',
+              },
+              {
+                label: t('routes.device.type.2'),
+                value: 9,
+                key: '9',
+              },
+              {
+                label: t('routes.device.type.3'),
+                value: 10,
+                key: '10',
+              },
+            ],
+          },
+        },
+        {
+          field: 'userName',
+          component: 'Input',
+          label: t('routes.device.userName'),
+          colProps: {
+            xl: 8,
+            xxl: 8,
           },
-          {
-            field: 'userName',
-            component: 'Input',
-            label: t('routes.device.userName'),
-            colProps: {
-              xl: 6,
-              xxl: 6,
+        },
+        {
+          field: 'incrementTypeId',
+          component: 'ApiSelect',
+          label: t('routes.equity.Type'),
+          componentProps: {
+            maxLength: 50,
+            api: async function () {
+              const list = await dincrementList();
+              return list.map((ele) => {
+                return { name: t(`routes.finance.equityType.${ele.validTimeType}`), value: ele.id };
+              });
             },
+            numberToString: true,
+            labelField: 'name',
+            valueField: 'value',
+            immediate: true,
+          },
+          colProps: {
+            xl: 8,
+            xxl: 8,
           },
-        ],
-      };
-      const [registerTable, { reload }] = useTable({
-        api: cameraList,
-        columns: columns,
-        searchInfo: { companyId },
-        useSearchForm: true,
-        formConfig: searchForm,
-        showTableSetting: true,
-        showIndexColumn:false,
-        rowKey: 'id',
-        beforeFetch:(T)=>{
-          if(T.ctivated){
-            T.activatedStartTime = T.ctivated[0]
-            T.activatedEndTime = T.ctivated[1]
-          }
-          return T
         },
-        fetchSetting: {
-          pageField: 'pageNum',
-          sizeField: 'pageSize',
-          listField: 'list',
-          totalField: 'total',
+        {
+          field: 'incrementStatus',
+          component: 'Select',
+          label: t('routes.device.statusName'),
+          colProps: {
+            xl: 8,
+            xxl: 8,
+          },
+          componentProps: {
+            options: [
+              {
+                label: t('routes.device.status.0'),
+                value: '0',
+                key: '0',
+              },
+              {
+                label: t('routes.device.status.1'),
+                value: '1',
+                key: '1',
+              },
+            ],
+          },
         },
-        canResize: false,
-      });
-      async function handleUnbind(record: Recordable) {
-        createConfirm({
-          iconType: 'warning',
-          title: () => h('span', t('common.optSuccess')),
-          content: '解绑后用户将看不到该相机拍摄的场景。<br/>确定解绑吗?',
-          onOk: async () => {
-            await UnbindCameraApi({cameraId:record.id})
-            createMessage.success(t('common.optSuccess'));
-            reload()
+        {
+          field: 'bindStatus',
+          component: 'Select',
+          label: t('routes.device.bindStatus'),
+          colProps: {
+            xl: 8,
+            xxl: 8,
           },
-        });
-      }
-      async function handleDelete(record: Recordable){
-        createConfirm({
-          iconType: 'warning',
-          title: () => h('span', t('common.optSuccess')),
-          content: '删除设备后需要重新入库<br/>确定删除吗?',
-          onOk: async () => {
-            await cameraDelete({id:record.id})
-            createMessage.success(t('common.optSuccess'));
-            reload()
+          componentProps: {
+            options: [
+              {
+                label: t('routes.device.status.2'),
+                value: '1',
+                key: '1',
+              },
+              {
+                label: t('routes.device.status.3'),
+                value: '0',
+                key: '0',
+              },
+            ],
           },
-        });
-      }
-      return {
-        registerTable,
-        handleUnbind,
-        reload,
-        handleDelete,
-        getCheckPerm,
-      };
-    },
-  });
+        },
+      ],
+    };
+    const [registerTable, { reload }] = useTable({
+      api: cameraList,
+      columns: columns,
+      searchInfo: { companyId },
+      useSearchForm: true,
+      formConfig: searchForm,
+      showTableSetting: true,
+      showIndexColumn: false,
+      rowKey: 'id',
+      beforeFetch: (T) => {
+        if (T.ctivated) {
+          T.activatedStartTime = T.ctivated[0];
+          T.activatedEndTime = T.ctivated[1];
+        }
+        return T;
+      },
+      fetchSetting: {
+        pageField: 'pageNum',
+        sizeField: 'pageSize',
+        listField: 'list',
+        totalField: 'total',
+      },
+      canResize: false,
+    });
+    async function handleUnbind(record: Recordable) {
+      createConfirm({
+        iconType: 'warning',
+        title: () => h('span', t('common.optSuccess')),
+        content: '解绑后用户将看不到该相机拍摄的场景。<br/>确定解绑吗?',
+        onOk: async () => {
+          await UnbindCameraApi({ cameraId: record.id });
+          createMessage.success(t('common.optSuccess'));
+          reload();
+        },
+      });
+    }
+    async function handleDelete(record: Recordable) {
+      createConfirm({
+        iconType: 'warning',
+        title: () => h('span', t('common.optSuccess')),
+        content: '删除设备后需要重新入库<br/>确定删除吗?',
+        onOk: async () => {
+          await cameraDelete({ id: record.id });
+          createMessage.success(t('common.optSuccess'));
+          reload();
+        },
+      });
+    }
+    return {
+      registerTable,
+      handleUnbind,
+      reload,
+      handleDelete,
+      getCheckPerm,
+    };
+  },
+});
 </script>
 <style lang="less" scoped>
-  .desc-wrap-BasicTable {
-    background-color: #f0f2f5;
-    .vben-basic-table-form-container {
-      padding: 0;
-    }
+.desc-wrap-BasicTable {
+  background-color: #f0f2f5;
+  .vben-basic-table-form-container {
+    padding: 0;
   }
+}
 </style>

+ 33 - 2
src/views/equity/EditModal.vue

@@ -21,12 +21,13 @@
   </BasicModal>
 </template>
 <script lang="ts">
-  import { defineComponent, nextTick, onMounted, reactive } from 'vue';
+  import { defineComponent, nextTick, onMounted, reactive, computed } from 'vue';
   import { BasicModal, useModalInner } from '/@/components/Modal';
   import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
   import { TableImg } from '/@/components/Table';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { InvoiceRegister, InvoiceDetail } from '/@/api/order';
+  import { useUserStore } from '/@/store/modules/user';
   import { useI18n } from '/@/hooks/web/useI18n';
   import { renewApi } from '/@/api/equity/index';
   import dayjs from 'dayjs';
@@ -42,8 +43,12 @@
       const fileFlow = reactive({
         file:null,
         type:2,//2-普通发票,3-专用发票
+        validTimeType: 0,
+        incrementEndTime:'',
       })
       const { createMessage } = useMessage();
+      const userStore = useUserStore();
+      const agent = computed(() => userStore.getAgent);
       const schemas: FormSchema[] = [
           {
             field: 'userName',
@@ -62,6 +67,27 @@
               span: 24,
             },
           },{
+            field: 'totalTime',
+            component: 'InputNumber',
+            label: t('routes.equity.totalTime'),
+            required: true,
+            defaultValue:1,
+            itemProps: {
+              validateTrigger: 'onBlur',
+            },
+            componentProps: {
+              max:agent.value.majorSubNum,
+              min:1,
+              onChange:(value)=>{
+                setFieldsValue({
+                  incrementEndTime:dayjs(fileFlow.incrementEndTime || new Date()).add(value,fileFlow.validTimeType == 0?'year':'month').format('YYYY-MM-DD')
+                });
+              }
+            },
+            colProps: {
+              span: 19,
+            },
+          },{
             field: 'incrementEndTime',
             component: 'DatePicker',
             label: t('routes.equity.expiryTime'),
@@ -97,8 +123,13 @@
       async function onDataReceive(data) {
         resetFields();
         // let detail = await InvoiceDetail({id:data.id})
-        console.log('InvoiceDetail',data)
         fileFlow.type = data.type
+        fileFlow.validTimeType = data.validTimeType
+        fileFlow.incrementEndTime = data.incrementEndTime
+        updateSchema([{
+          field: 'count',
+          suffix:`${t('routes.equity.syks')} ${data.validTimeType != 0?agent.value.highSubNum:agent.value.majorSubNum} ${data.validTimeType != 0?t('routes.equity.unit.-2'):t('routes.equity.unit.-1')}`, 
+        }])
         setFieldsValue({
           ...data,
           incrementEndTime:dayjs(data.isExpired == 1?new Date():data.incrementEndTime).add(1,data.validTimeType == 0?'year':'month').format('YYYY-MM-DD')

+ 61 - 4
src/views/equity/InvoiceModal.vue

@@ -104,11 +104,16 @@
               onChange:(value)=>{
                 updateSchema([{
                   field: 'count',
-                  suffix:`${t('routes.equity.syks')} ${value == 3?agent.value.highSubNum:agent.value.majorSubNum} ${t('routes.equity.unit.1')}`, 
                   componentProps: {
                     max:value == 3?agent.value.highSubNum:agent.value.majorSubNum,
                     min:1,
                   },
+                },{
+                  field: 'totalTime',
+                  suffix:`${t('routes.equity.syks')} ${value == 3?agent.value.highSubNum:agent.value.majorSubNum} ${value == 3?t('routes.equity.unit.-2'):t('routes.equity.unit.-1')}`, 
+                  componentProps: {
+                    options: timeOption(value)
+                  },
                 }])
                 setFieldsValue({
                   count:1,
@@ -124,7 +129,7 @@
             component: 'InputNumber',
             label: t('routes.equity.countNumber'),
             required: true,
-            suffix:`${t('routes.equity.syks')} ${agent.value.majorSubNum} ${t('routes.equity.unit.1')}`,
+            // suffix:`${t('routes.equity.syks')} ${agent.value.majorSubNum} ${t('routes.equity.unit.1')}`,
             defaultValue:1,
             itemProps: {
               validateTrigger: 'onBlur',
@@ -132,6 +137,31 @@
             componentProps: {
               max:agent.value.majorSubNum,
               min:1,
+              onChange:(value)=>{
+                setFieldsValue({
+                  incrementEndTime:dayjs(fileFlow.incrementEndTime || new Date()).add(value,fileFlow.validTimeType == 0?'year':'month').format('YYYY-MM-DD')
+                });
+              }
+            },
+            colProps: {
+              span: 19,
+            },
+          },{
+            field: 'totalTime',
+            component: 'Select',
+            label: t('routes.equity.totalTime'),
+            required: true,
+            suffix:`${t('routes.equity.syks')} ${agent.value.majorSubNum} ${t('routes.equity.unit.1')}`,
+            itemProps: {
+              validateTrigger: 'onBlur',
+            },
+            componentProps: {
+              options:[],
+              onChange:(value)=>{
+                setFieldsValue({
+                  incrementEndTime:dayjs(fileFlow.incrementEndTime || new Date()).add(value,fileFlow.validTimeType == 0?'year':'month').format('YYYY-MM-DD')
+                });
+              }
             },
             colProps: {
               span: 19,
@@ -156,7 +186,7 @@
           }
       ];
 
-      const [registerForm, { validate, resetFields, setFieldsValue, updateSchema }] = useForm({
+      const [registerForm, { validate, resetFields, setFieldsValue, updateSchema, getFieldsValue }] = useForm({
         labelWidth: 120,
         schemas:schemas,
         showActionButtonGroup: false,
@@ -178,7 +208,8 @@
           {field: 'shipNum',ifShow:fileFlow.type == 3,},
           {field: 'email',ifShow:fileFlow.type == 2,},
           {field: 'file',ifShow:fileFlow.type == 2,},
-          {field: 'count',suffix:`${t('routes.equity.syks')} ${agent.value.majorSubNum} ${t('routes.equity.unit.1')}`,componentProps:{
+          {field: 'totalTime',suffix:`${t('routes.equity.syks')} ${agent.value.majorSubNum} ${t('routes.equity.unit.1')}`,},
+          {field: 'count',componentProps:{
               max:agent.value.majorSubNum,
               min:1,
             }},
@@ -187,6 +218,12 @@
       const handleSubmit = async () => {
         // try {
           const params = await validate();
+          console.log('params',params)
+          let timeVal = params.incrementTypeId == 3?agent.value.highSubNum:agent.value.majorSubNum
+          if((params.count * params.totalTime)>timeVal){
+            createMessage.error(t('routes.equity.totalMessge'));
+            return
+          }
           await addApi(params);
           closeModal();
           resetFields();
@@ -199,6 +236,25 @@
       function handleVisibleChange(v) {
         v && props.userData && nextTick(() => onDataReceive(props.userData));
       }
+      function timeOption(incrementTypeId) {
+        let list = []
+        let timeVal = incrementTypeId == 3?agent.value.highSubNum:agent.value.majorSubNum
+        let value = 10, unit = '年'
+        if(incrementTypeId == 3){//高级会员月
+          value = timeVal>12?12:timeVal
+          unit = '个月'
+        }else{
+          value = timeVal>10?10:timeVal
+        }
+        for (let index = 1; index <= value; index++) {
+          list.push({
+            label: index+unit,
+            value: index,
+            key: index,
+          })
+        }
+        return list
+      }
       return {
         register,
         registerForm,
@@ -207,6 +263,7 @@
         handleSubmit,
         addListFunc,
         resetFields,
+        timeOption,
         t,
       };
     },

+ 7 - 1
src/views/finance/data.tsx

@@ -58,6 +58,12 @@ export const columns: BasicColumn[] = [
     width: 120,
   },
   {
+    title: t('routes.equity.totalTime'),
+    dataIndex: 'totalTime',
+    // slots: { customRender: 'orderStatus' },
+    width: 120,
+  },
+  {
     title: t('routes.equity.giveType'),
     dataIndex: 'giveType',
     // slots: { customRender: 'orderStatus' },
@@ -139,7 +145,7 @@ export const searchForm: Partial<FormProps> = {
     },
     {
       field: 'timeList',
-      label: t('routes.equity.timeList'),
+      label: t('routes.scene.createTime'),
       component: 'RangePicker',
       componentProps: {
         maxLength: 100,

+ 3 - 3
src/views/finance/index.vue

@@ -69,15 +69,15 @@ export default defineComponent({
         // icon: 'fa6-solid:users-gear',
         icon: 'visit-count|svg',
         value: lastMajorNum || 0,
-        unit: t('routes.equity.unit.1'),
-        color: 'blue',
+        unit: t('routes.equity.unit.-1'),
+        color: 'green',
         action: t('routes.equity.unit.-2'),
       },
       {
         title:  t('routes.equity.CardHighNum'),
         icon: 'akar-icons:person-add',
         value: lastHighNum || 0,
-        unit: t('routes.equity.unit.1'),
+        unit: t('routes.equity.unit.-2'),
         color: 'blue',
         action: t('routes.equity.unit.-2'),
       },

+ 201 - 0
src/views/loglist/index.vue

@@ -0,0 +1,201 @@
+<template>
+  <div class="desc-wrap-BasicTable">
+    <BasicTable @register="registerTable"> </BasicTable>
+  </div>
+</template>
+<script lang="ts">
+import { defineComponent, onMounted } from 'vue';
+import {
+  BasicTable,
+  useTable,
+  TableAction,
+  BasicColumn,
+  TableImg,
+  FormProps,
+} from '/@/components/Table';
+import { useI18n } from '/@/hooks/web/useI18n';
+import { usePermissionStore } from '/@/store/modules/permission';
+import { dincrementList, cameraIncrementLog } from '/@/api/equity';
+export default defineComponent({
+  components: {
+    BasicTable,
+    TableAction,
+    TableImg,
+  },
+  setup() {
+    const { t } = useI18n();
+    const permissionStore = usePermissionStore();
+    const { getCheckPerm } = permissionStore;
+    onMounted(() => {
+      // console.log(router.currentRoute.value.params.id);
+    });
+    const columns: BasicColumn[] = [
+      {
+        title: t('routes.device.snCode'),
+        dataIndex: 'snCode',
+        width: 180,
+      },
+      {
+        title: t('routes.equity.operationType'),
+        dataIndex: 'operationType',
+        width: 150,
+        customRender: ({ record }) => {
+          return record.operationType?t('routes.equity.operation.1'):t('routes.equity.operation.0');
+        },
+      },
+      {
+        title: t('routes.equity.operationUserName'),
+        dataIndex: 'operationUserName',
+        ellipsis: false,
+        width: 80,
+        customRender: ({ record }) => {
+          return record.operationUserName || t('routes.equity.platform');
+        },
+      },
+      {
+        title: t('routes.equity.operationTime'),
+        dataIndex: 'createTime',
+        width: 180,
+      },
+      {
+        title: t('routes.equity.Type'),
+        dataIndex: 'validTimeType',
+        width: 180,
+        customRender({ record }) {
+          return record.validTimeType==0 ?t('routes.equity.equityType.0'):record.validTimeType==1? t('routes.equity.equityType.3') : t('routes.device.NoBind');
+        },
+      },
+      {
+        title: t('routes.equity.incrementId'),
+        dataIndex: 'incrementId',
+        width: 180,
+        // customRender({ record }) {
+        //   return record.userName ? record.userName : '-';
+        // },
+      },
+    ];
+    const searchForm: Partial<FormProps> = {
+      labelWidth: 120,
+      autoAdvancedLine: 1,
+      actionColOptions: {
+        span: 24,
+      },
+      schemas: [
+        {
+          field: 'snCode',
+          component: 'Input',
+          label: t('routes.device.snCode'),
+          colProps: {
+            xl: 8,
+            xxl: 8,
+          },
+        },
+        {
+          field: 'type',
+          component: 'Select',
+          label: t('routes.equity.operationType'),
+          colProps: {
+            xl: 8,
+            xxl: 8,
+          },
+          componentProps: {
+            options: [
+              {
+                  label: t('routes.equity.operation.0'),
+                  value: 0,
+                  key: '0',
+                },{
+                label: t('routes.equity.operation.1'),
+                value: 1,
+                key: '1',
+              }
+            ],
+          },
+        },
+        {
+          field: 'incrementTypeId',
+          component: 'ApiSelect',
+          label: t('routes.equity.Type'),
+          componentProps: {
+            maxLength: 50,
+            api: async function () {
+              const list = await dincrementList();
+              return list.map((ele) => {
+                return { name: t(`routes.finance.equityType.${ele.validTimeType}`), value: ele.id };
+              });
+            },
+            numberToString: true,
+            labelField: 'name',
+            valueField: 'value',
+            immediate: true,
+          },
+          colProps: {
+            xl: 8,
+            xxl: 8,
+          },
+        },
+        {
+          field: 'operationUser',
+          component: 'Input',
+          label: t('routes.equity.operationUserName'),
+          colProps: {
+            xl: 8,
+            xxl: 8,
+          },
+        },
+        {
+          field: 'timeList',
+          label: t('routes.equity.operationTime'),
+          component: 'RangePicker',
+          componentProps: {
+            maxLength: 100,
+            format: 'YYYY-MM-DD',
+            valueFormat: 'YYYY-MM-DD',
+            showTime: true,
+          },
+          colProps: {
+            xl: 8,
+            xxl: 8,
+          },
+        },
+      ],
+    };
+    const [registerTable, { reload }] = useTable({
+      api: cameraIncrementLog,
+      columns: columns,
+      useSearchForm: true,
+      formConfig: searchForm,
+      showTableSetting: true,
+      showIndexColumn: false,
+      rowKey: 'id',
+      beforeFetch: (T) => {
+        if (T.ctivated) {
+          T.activatedStartTime = T.ctivated[0];
+          T.activatedEndTime = T.ctivated[1];
+        }
+        return T;
+      },
+      fetchSetting: {
+        pageField: 'pageNum',
+        sizeField: 'pageSize',
+        listField: 'list',
+        totalField: 'total',
+      },
+      canResize: false,
+    });
+    return {
+      registerTable,
+      reload,
+      getCheckPerm,
+    };
+  },
+});
+</script>
+<style lang="less" scoped>
+.desc-wrap-BasicTable {
+  background-color: #f0f2f5;
+  .vben-basic-table-form-container {
+    padding: 0;
+  }
+}
+</style>

+ 34 - 4
src/views/scene/list.vue

@@ -226,7 +226,11 @@
         },
       ];
       const searchForm: Partial<FormProps> = {
-        labelWidth: 100,
+        labelWidth: 130,
+        autoAdvancedLine:1,
+        actionColOptions: {
+          span: 24,
+        },
         schemas: [
           {
             field: 'sceneName',
@@ -241,6 +245,19 @@
             },
           },
           {
+            
+            label: t('routes.scene.num'),
+            field: 'num',
+            component: 'Input',
+            componentProps: {
+              maxLength: 100,
+            },
+            colProps: {
+              xl: 7,
+              xxl: 7,
+            },
+          },
+          {
             field: 'snCode',
             label: t('routes.scene.snCode'),
             component: 'Input',
@@ -260,10 +277,23 @@
               maxLength: 100,
             },
             colProps: {
-              xl: 6,
-              xxl: 6,
+              xl: 7,
+              xxl: 7,
             },
-          },
+          },    {
+      field: 'timeList',
+      label: t('routes.equity.timeList'),
+      component: 'RangePicker',
+      componentProps: {
+        maxLength: 100,
+        valueFormat: 'YYYY-MM-DD',
+        format: 'YYYY-MM-DD',
+      },
+      colProps: {
+        xl: 7,
+        xxl: 7,
+      },
+    },
         ],
       };
       function cancelDownload() {