Przeglądaj źródła

feat: 完善获取cld列表地区代码

lanjianrong 4 lat temu
rodzic
commit
a2784d0c2c

+ 3 - 10
.vscode/settings.json

@@ -1,6 +1,6 @@
 {
   "typescript.tsdk": "./node_modules/typescript/lib",
-  "volar.tsPlugin": true,
+  "volar.tsPlugin": false,
   "volar.tsPluginStatus": false,
   //===========================================
   //============= Editor ======================
@@ -108,14 +108,7 @@
     "extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"]
     // "configFile": "C:\\Users\\12442\\AppData\\Local\\Yarn\\Data\\global\\node_modules\\.eslintrc.js"
   },
-  "eslint.validate": [
-    "javascript",
-    "typescript",
-    "reacttypescript",
-    "reactjavascript",
-    "html",
-    "vue"
-  ],
+  "eslint.validate": ["javascript", "typescript", "reacttypescript", "reactjavascript", "html", "vue"],
   // ===========================================
   // ================ Vetur ====================
   // ===========================================
@@ -178,7 +171,7 @@
   },
   "[vue]": {
     "editor.codeActionsOnSave": {
-      "source.fixAll.eslint": true,
+      // "source.fixAll.eslint": false,
       "source.fixAll.stylelint": true
     }
   },

+ 26 - 1
src/api/sys/model/projectModel.ts

@@ -26,7 +26,7 @@ export interface ProjectListItem {
   status: number
 }
 
-export type ProjectDetailParams = {
+export type ProjectUpdateOrCreateParams = {
   id: string
   name: string
   insideCategoryId: string
@@ -39,7 +39,32 @@ export type ProjectDetailParams = {
   status: string
 }
 
+export type ProjectAccountParams = {
+  id?: string
+  projectId: string
+}
+
+export type ProjectAccountItem = {
+  id: string
+  projectId: string
+  bidsectionId: string
+  account: string
+  password: string
+  name: string
+  company: string
+  position: string
+  role: string
+  mobile: string
+  telephone: string
+  isAdmin: number
+  accountGroup: number
+  enable: number
+  contractPermission: string
+  qualityPermission: string
+  safePermission: string
+}
 /**
  * @description: Request list return value
  */
 export type ProjectListGetResultModel = BasicFetchResult<ProjectListItem[]>
+export type ProjectAccountListResultModal = ProjectAccountItem[]

+ 27 - 3
src/api/sys/project.ts

@@ -3,12 +3,16 @@ import {
   ProjectListGetResultModel,
   ProjectListParams,
   ProjectListItem,
-  ProjectDetailParams
+  ProjectUpdateOrCreateParams,
+  ProjectAccountParams,
+  ProjectAccountListResultModal
 } from './model/projectModel'
 enum Api {
   GetProjectList = '/backstage/project/list',
   GetProjectDetail = '/backstage/project',
-  UpdateProjectDetail = '/backstage/project/save'
+  UpdateProjectDetail = '/backstage/project/save',
+  AddProject = '/backstage/project/add',
+  GetProjectAccount = '/backstage/account'
 }
 
 /**
@@ -32,11 +36,31 @@ export function getProjectById(params: { id: string }) {
 }
 
 /**
+ * @description 新增项目
+ */
+export function addProject(params: ProjectUpdateOrCreateParams) {
+  return defHttp.post({
+    url: Api.AddProject,
+    params
+  })
+}
+
+/**
  * @description 编辑项目
  */
-export function updateProject(params: ProjectDetailParams) {
+export function updateProject(params: ProjectUpdateOrCreateParams) {
   return defHttp.post({
     url: Api.UpdateProjectDetail,
     params
   })
 }
+
+/**
+ * @description 获取项目账号信息列表
+ */
+export function getProjectAccount(params: ProjectAccountParams) {
+  return defHttp.get<ProjectAccountListResultModal>({
+    url: Api.GetProjectAccount,
+    params
+  })
+}

+ 5 - 0
src/store/modules/office.ts

@@ -43,6 +43,11 @@ export const useOfficeStore = defineStore({
     async getStaffWithCategoryIdAction(params: OfficeListParams) {
       const { staff = [] } = await getOfficeList(params)
       this.setStaffList(staff.map(item => ({ value: item.sid, label: item.username })))
+    },
+    checkStaffList() {
+      if (!this.getCategories.length) {
+        this.getOfficesAction()
+      }
     }
   }
 })

+ 0 - 1
src/utils/http/axios/index.ts

@@ -99,7 +99,6 @@ const transform: AxiosTransform = {
       Promise.reject(new Error(timeoutMsg))
       return errorResult
     }
-    console.log(errorResult)
 
     return errorResult
   },

+ 106 - 0
src/views/dashboard/project-detail/components/account.vue

@@ -0,0 +1,106 @@
+<template>
+  <BasicTable @register="registerTable">
+    <template #toolbar>
+      <div class="w-2/5 flex">
+        <!-- <Search @search="value => handleSearch('search', value)" placeholder="项目名称/项目编号" /> -->
+        <a-button @click="showModalFn" class="ml-3"><PlusOutlined />新增账号</a-button>
+      </div>
+    </template>
+  </BasicTable>
+  <BasicModal @register="registerModal" @ok="submitModal">
+    <BasicForm @register="registerForm" ref="formElRef" />
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { computed, defineComponent, PropType, ref, watch } from 'vue'
+  import { BasicTable, useTable } from '/@/components/Table'
+  import { BasicModal, useModal } from '/@/components/Modal'
+  import { BasicForm, FormActionType, FormSchema, useForm } from '/@/components/Form/index'
+  import { getTableColumns } from './tableData'
+  import { getProjectAccount } from '/@/api/sys/project'
+  import { useGo } from '/@/hooks/web/usePage'
+  export default defineComponent({
+    name: 'ProjectDetailAccount',
+    components: {
+      BasicTable,
+      BasicModal,
+      BasicForm
+    },
+    props: {
+      id: {
+        type: String as PropType<string>,
+        default: null
+      },
+      activeId: {
+        type: String as PropType<string>,
+        default: '1'
+      }
+    },
+    setup(props) {
+      const formElRef = ref<Nullable<FormActionType>>(null)
+
+      const go = useGo()
+      const [registerTable, { setTableData }] = useTable({
+        columns: getTableColumns(() => go('/acount/detail')),
+        canResize: true
+      })
+      const fetchTableData = async (projectId: string) => {
+        const data = await getProjectAccount({ projectId })
+        setTableData(data)
+      }
+      watch(
+        props,
+        newProps => {
+          console.log(newProps.activeId)
+
+          if (newProps.activeId === '2') {
+            fetchTableData(props.id)
+          }
+        },
+        { immediate: true }
+      )
+      const [registerModal, { openModal, setModalProps }] = useModal()
+      const schemas = computed<FormSchema[]>(() => [
+        {
+          field: 'account',
+          component: 'Input',
+          label: '登录账号',
+          required: true
+        },
+        {
+          field: 'password',
+          component: 'InputPassword',
+          label: '登录密码',
+          required: true
+        },
+        {
+          field: 'name',
+          component: 'Input',
+          label: '姓名',
+          required: true
+        }
+      ])
+      const [registerForm] = useForm({
+        labelWidth: 120,
+        schemas,
+        showActionButtonGroup: false
+      })
+
+      async function showModalFn() {
+        openModal()
+        setModalProps({
+          title: '新增项目',
+          okText: '确认添加'
+        })
+      }
+
+      function submitModal() {
+        formElRef.value?.validate().then(() => {
+          // createProject(values)
+        })
+      }
+
+      return { registerTable, registerModal, registerForm, showModalFn, submitModal }
+    }
+  })
+</script>

+ 95 - 113
src/views/dashboard/project-detail/components/info.vue

@@ -4,99 +4,15 @@
   </div>
 </template>
 <script lang="ts">
-  import { defineComponent, computed, unref, watch, PropType } from 'vue'
+  import { defineComponent, computed, unref, PropType } from 'vue'
   import { BasicForm, FormSchema, useForm } from '/@/components/Form/index'
   import { ProjectStatusEnum } from '/@/enums/statusEnum'
   import { useOfficeStore } from '/@/store/modules/office'
-  import { ProjectListItem, ProjectDetailParams } from '/@/api/sys/model/projectModel'
+  import { ProjectListItem, ProjectUpdateOrCreateParams } from '/@/api/sys/model/projectModel'
   import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated'
   import { updateProject } from '/@/api/sys/project'
   import { useMessage } from '/@/hooks/web/useMessage'
-  const schemas: FormSchema[] = [
-    {
-      field: 'status',
-      component: 'RadioGroup',
-      label: '状态',
 
-      componentProps: {
-        options: [
-          {
-            label: '正常',
-            value: ProjectStatusEnum.NORMAL
-          },
-          {
-            label: '停用',
-            value: ProjectStatusEnum.STOP
-          }
-        ]
-      }
-    },
-    {
-      field: 'createName',
-      component: 'Input',
-      label: '创建者',
-      componentProps: {
-        disabled: true
-      }
-    },
-    {
-      field: 'code',
-      component: 'Input',
-      label: '项目编号',
-
-      componentProps: {
-        disabled: true
-      }
-    },
-    {
-      field: 'name',
-      component: 'Input',
-      label: '项目名称',
-
-      required: true
-    },
-    {
-      field: 'insideCategoryId',
-      component: 'Select',
-      componentProps: {
-        showArrow: true
-      },
-      label: '所在办事处',
-
-      required: true
-    },
-    {
-      field: 'categoryId',
-      component: 'Select',
-      label: '销售负责人',
-      componentProps: {
-        showArrow: true
-      },
-      colProps: {
-        span: 14
-      },
-      required: true
-    },
-    {
-      field: 'staffId',
-      component: 'Select',
-      disabledLabelWidth: true,
-      componentProps: {
-        showArrow: true
-      },
-      label: '',
-      colProps: {
-        span: 8,
-        offset: 2
-      },
-      required: true
-    },
-    {
-      field: 'remark',
-      component: 'InputTextArea',
-      label: '备注'
-    }
-  ]
   export default defineComponent({
     components: {
       BasicForm
@@ -119,7 +35,94 @@
       const options = computed(() => officeStore.getCategoryOptions)
       const staffOptions = computed(() => officeStore.getCategoriedStaff)
 
-      const [register, { updateSchema, setFieldsValue, removeSchemaByFiled, appendSchemaByField }] = useForm({
+      const schemas = computed<FormSchema[]>(() => [
+        {
+          field: 'status',
+          component: 'RadioGroup',
+          label: '状态',
+          componentProps: {
+            options: [
+              {
+                label: '正常',
+                value: ProjectStatusEnum.NORMAL
+              },
+              {
+                label: '停用',
+                value: ProjectStatusEnum.STOP
+              }
+            ]
+          }
+        },
+        {
+          field: 'createName',
+          component: 'Input',
+          label: '创建者',
+          componentProps: {
+            disabled: true
+          }
+        },
+        {
+          field: 'code',
+          component: 'Input',
+          label: '项目编号',
+
+          componentProps: {
+            disabled: true
+          }
+        },
+        {
+          field: 'name',
+          component: 'Input',
+          label: '项目名称',
+
+          required: true
+        },
+        {
+          field: 'insideCategoryId',
+          component: 'Select',
+          componentProps: {
+            options,
+            showArrow: true
+          },
+          label: '所在办事处',
+
+          required: true
+        },
+        {
+          field: 'categoryId',
+          component: 'Select',
+          label: '销售负责人',
+          componentProps: {
+            options,
+            showArrow: true
+          },
+          colProps: {
+            span: 14
+          },
+          required: true
+        },
+        {
+          field: 'staffId',
+          component: 'Select',
+          disabledLabelWidth: true,
+          componentProps: {
+            options: staffOptions,
+            showArrow: true
+          },
+          label: '',
+          colProps: {
+            span: 8,
+            offset: 2
+          },
+          required: true
+        },
+        {
+          field: 'remark',
+          component: 'InputTextArea',
+          label: '备注'
+        }
+      ])
+      const [register, { updateSchema, setFieldsValue }] = useForm({
         labelWidth: 120,
         schemas,
         actionColOptions: {
@@ -131,15 +134,13 @@
         }
       })
       async function checkOffice() {
-        if (!officeStore.getOfficesAction.length) {
-          await officeStore.getOfficesAction()
-        }
+        officeStore.checkStaffList()
         if (props.info.categoryId) {
           await officeStore.getStaffWithCategoryIdAction({ categoryId: props.info.categoryId })
         }
       }
+      checkOffice()
       onMountedOrActivated(async () => {
-        await checkOffice()
         await updateSchema([
           {
             field: 'insideCategoryId',
@@ -167,27 +168,7 @@
         ])
         await setFieldsValue({ ...unref(info) })
       })
-      watch(staffOptions, async newStaffOtpions => {
-        await removeSchemaByFiled('staffId')
-        await appendSchemaByField(
-          {
-            field: 'staffId',
-            component: 'Select',
-            label: '',
-            componentProps: {
-              showArrow: true,
-              options: newStaffOtpions
-            },
-            disabledLabelWidth: true,
-            colProps: {
-              span: 8,
-              offset: 2
-            },
-            required: true
-          },
-          'categoryId'
-        )
-      })
+
       const handleOnSave = async (values: {
         name: string
         insideCategoryId: string
@@ -196,7 +177,7 @@
         remark: string
         status: string
       }) => {
-        const newVal: ProjectDetailParams = {
+        const newVal: ProjectUpdateOrCreateParams = {
           ...values,
           id: props.info.id,
           insideCategory: '',
@@ -213,6 +194,7 @@
           newVal.staffName = staffOptions.value.find(item => item.value === values.staffId)?.label || ''
         }
         await updateProject(newVal)
+        info.value = { ...info.value, ...newVal }
       }
       function handleSubmit(values) {
         try {

+ 47 - 0
src/views/dashboard/project-detail/components/tableData.tsx

@@ -0,0 +1,47 @@
+import { BasicColumn } from '/@/components/Table/src/types/table'
+import { Icon } from '/@/components/Icon/index'
+export function getTableColumns(fn: (id: string) => void): BasicColumn[] {
+  return [
+    {
+      dataIndex: 'account',
+      title: '账号',
+      customRender: ({ text, record }) => (
+        <div>
+          {record.isAdmin ? <Icon type="clarity:administrator-solid" /> : null}
+          {text}
+        </div>
+      )
+    },
+    {
+      dataIndex: 'name',
+      title: '姓名'
+    },
+    {
+      dataIndex: 'company',
+      title: '单位'
+    },
+    {
+      dataIndex: 'position',
+      title: '角色/职位'
+    },
+    {
+      dataIndex: 'mobile',
+      title: '手机'
+    },
+    {
+      dataIndex: 'telephone',
+      title: '电话'
+    },
+    {
+      dataIndex: 'action',
+      title: '操作',
+      customRender: ({ record }) => (
+        <div>
+          <a-button type="primary" onClick={() => fn(record.id)}>
+            编辑
+          </a-button>
+        </div>
+      )
+    }
+  ]
+}

+ 14 - 15
src/views/dashboard/project-detail/index.vue

@@ -13,11 +13,13 @@
       <h4 class="text-3xl p-0 m-0">{{ projectInfo.name }}</h4>
     </div>
     <div>
-      <a-tabs default-active-key="1">
+      <a-tabs :default-active-key="activeKey" @change="tabChange">
         <a-tab-pane key="1" tab="项目信息">
           <ProjectInfo v-if="projectInfo" :info="projectInfo" @updateInfo:info="updateInfo" />
         </a-tab-pane>
-        <a-tab-pane key="2" tab="项目账号" />
+        <a-tab-pane key="2" tab="项目账号">
+          <ProjectAccount :active-id="activeKey" :id="projectInfo?.id" />
+        </a-tab-pane>
         <a-tab-pane key="3" tab="项目标段" />
         <a-tab-pane key="4" tab="办事处共享" />
         <a-tab-pane key="5" tab="功能设置" />
@@ -35,33 +37,25 @@
   import { useDesign } from '/@/hooks/web/useDesign'
   import { projectStatusBgColorMap, projectStatusTextMap } from '/@/enums/statusEnum'
   import ProjectInfo from './components/info.vue'
-  import { useOfficeStore } from '/@/store/modules/office'
+  import ProjectAccount from './components/account.vue'
   export default defineComponent({
     name: 'Project',
     components: {
       PageWrapper,
       ATabs: Tabs,
       ATabPane: Tabs.TabPane,
-      ProjectInfo
+      ProjectInfo,
+      ProjectAccount
     },
     setup() {
+      const activeKey = ref('1')
       const { prefixCls } = useDesign('project')
       const projectInfo = ref<Nullable<ProjectListItem>>(null)
       const route = useRoute()
       async function fetchProjectInfo(id: string) {
         const project = await getProjectById({ id })
         projectInfo.value = project
-        if (project.staffId) {
-          await officeStore.getStaffWithCategoryIdAction({ categoryId: project.categoryId })
-        }
-      }
-      const officeStore = useOfficeStore()
-      async function checkOffice() {
-        if (!officeStore.getOfficesAction.length) {
-          await officeStore.getOfficesAction()
-        }
       }
-      checkOffice()
       fetchProjectInfo(route.params.id as string)
       watch(
         () => route.params.id,
@@ -74,7 +68,12 @@
       const updateInfo = (info: ProjectListItem) => {
         projectInfo.value = info
       }
-      return { projectInfo, projectStatusBgColorMap, projectStatusTextMap, prefixCls, updateInfo }
+
+      const tabChange = (key: string) => {
+        activeKey.value = key
+      }
+
+      return { activeKey, projectInfo, projectStatusBgColorMap, projectStatusTextMap, prefixCls, updateInfo, tabChange }
     }
   })
 </script>

+ 127 - 10
src/views/dashboard/workbench/index.vue

@@ -2,9 +2,10 @@
   <PageWrapper>
     <BasicTable @register="registerTable">
       <template #toolbar>
-        <span class="w-1/5">
+        <div class="w-2/5 flex">
           <Search @search="value => handleSearch('search', value)" placeholder="项目名称/项目编号" />
-        </span>
+          <a-button @click="showModalFn" class="ml-3"><PlusOutlined />新增项目</a-button>
+        </div>
       </template>
       <template #filterDropdown="{ setSelectedKeys, selectedKeys, confirm, clearFilters }">
         <div class="p-3">
@@ -12,8 +13,7 @@
             :options="options"
             placeholder="按办事处筛选"
             @select="value => setSelectedKeys([value])"
-            style="width: 180px"
-            allowClear
+            allowclear
           />
         </div>
         <div class="pb-3 justify-center flex">
@@ -24,34 +24,101 @@
         </div>
       </template>
     </BasicTable>
+    <BasicModal @register="registerModal" @ok="submitModal">
+      <BasicForm @register="registerForm" ref="formElRef" />
+    </BasicModal>
   </PageWrapper>
 </template>
 <script lang="ts">
-  import { computed, defineComponent } from 'vue'
+  import { computed, defineComponent, ref } from 'vue'
   import { BasicTable, useTable } from '/@/components/Table'
+  import { BasicModal, useModal } from '/@/components/Modal'
+  import { BasicForm, FormActionType, FormSchema, useForm } from '/@/components/Form/index'
+  import { PlusOutlined } from '@ant-design/icons-vue'
   import { PageWrapper } from '/@/components/Page'
   import { getProjectList } from '/@/api/sys/project'
   import { Input, Select } from 'ant-design-vue'
   import { getProjectTableColumns } from './tableData'
   import { useOfficeStore } from '/@/store/modules/office'
-  import { ProjectListItem, ProjectListParams } from '/@/api/sys/model/projectModel'
+  import { ProjectListItem, ProjectListParams, ProjectUpdateOrCreateParams } from '/@/api/sys/model/projectModel'
+  import { addProject } from '/@/api/sys/project'
+  import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated'
+  import { useMessage } from '/@/hooks/web/useMessage'
+
   export default defineComponent({
     name: 'Workbench',
     components: {
       PageWrapper,
       BasicTable,
       Search: Input.Search,
-      ASelect: Select
+      ASelect: Select,
+      BasicModal,
+      BasicForm,
+      PlusOutlined
     },
     setup() {
+      const { createMessage } = useMessage()
+      const formElRef = ref<Nullable<FormActionType>>(null)
       const officeStore = useOfficeStore()
       const options = computed(() => officeStore.getCategoryOptions)
+      const staffOptions = computed(() => officeStore.getCategoriedStaff)
+      const schemas = computed<FormSchema[]>(() => [
+        {
+          field: 'code',
+          component: 'Input',
+          label: '项目编号',
+          required: true
+        },
+        {
+          field: 'name',
+          component: 'Input',
+          label: '项目名称',
+          required: true
+        },
+        {
+          field: 'categoryId',
+          component: 'Select',
+          label: '销售负责人',
+          componentProps: {
+            options,
+            showArrow: true,
+            onChange: async (value: string) => {
+              officeStore.getStaffWithCategoryIdAction({ categoryId: value })
+              const formRef = formElRef.value
+              formRef?.setFieldsValue({ staffId: '' })
+            }
+          },
+          colProps: {
+            span: 15
+          },
+          required: true
+        },
+        {
+          field: 'staffId',
+          component: 'Select',
+          disabledLabelWidth: true,
+          componentProps: {
+            showArrow: true,
+            options: staffOptions
+          },
+          label: '',
+          colProps: {
+            span: 8,
+            offset: 1
+          }
+        },
+        {
+          field: 'remark',
+          label: '备注',
+          component: 'InputTextArea'
+        }
+      ])
       async function checkOffice() {
         if (!officeStore.getOfficesAction.length) {
           await officeStore.getOfficesAction()
         }
       }
-      const [registerTable, { setTableData }] = useTable({
+      const [registerTable, { setTableData, reload }] = useTable({
         canResize: true,
         title: '项目列表',
         rowKey: 'id',
@@ -60,7 +127,17 @@
         showTableSetting: true
       })
 
-      checkOffice()
+      const [registerModal, { openModal, setModalProps }] = useModal()
+      const [registerForm] = useForm({
+        labelWidth: 120,
+        schemas,
+        showActionButtonGroup: false
+      })
+
+      onMountedOrActivated(async () => {
+        checkOffice()
+      })
+
       async function handleSearch(key: keyof ProjectListParams, value: string, fn?: Fn) {
         if (fn) {
           fn()
@@ -69,7 +146,47 @@
           setTableData<ProjectListItem>(tableData.items)
         }
       }
-      return { registerTable, options, handleSearch }
+      async function showModalFn() {
+        openModal()
+        setModalProps({
+          title: '新增项目',
+          okText: '确认添加'
+        })
+      }
+
+      function submitModal() {
+        formElRef.value?.validate().then((values: ProjectUpdateOrCreateParams) => {
+          createProject(values)
+        })
+      }
+
+      async function createProject(values: ProjectUpdateOrCreateParams) {
+        const newVals = { ...values }
+        if (values.categoryId) {
+          newVals.category = options.value.find(item => item.value === values.categoryId)?.label || ''
+        }
+        if (values.staffId) {
+          newVals.staffName = staffOptions.value.find(item => item.value === values.staffId)?.label || ''
+        }
+        try {
+          await addProject(newVals)
+        } finally {
+          openModal(false)
+          reload()
+          createMessage.success('新建项目成功')
+        }
+      }
+
+      return {
+        showModalFn,
+        registerTable,
+        options,
+        handleSearch,
+        registerModal,
+        registerForm,
+        submitModal,
+        formElRef
+      }
     }
   })
 </script>