ljy121 hace 1 año
padre
commit
3dc9619760

BIN
LOG_FILE_IS_UNDEFINED.2023-11-30.0.gz


+ 266 - 0
client/src/views/OaSystem/projectCenter/projectBook/deptProject.vue

@@ -0,0 +1,266 @@
+<template>
+  <div class="_ProjectCenterBook">
+    <div class="searchBox">
+      <div class="form">
+        <span class="formSpan">项目名称:</span>
+        <el-input v-model="queryParams.xmmc" placeholder="请输入项目名称" style="width: 210px" />
+      </div>
+      <div class="form">
+        <span class="formSpan">项目编号:</span>
+        <el-input v-model="queryParams.xmbh" placeholder="请输入项目名称" style="width: 160px" />
+      </div>
+      <div class="form">
+        <span class="formSpan">行政区:</span>
+        <div style="width: 160px">
+          <el-tree-select
+            v-model="queryParams.xzqdm"
+            node-key="id"
+            check-strictly
+            filterable
+            :filter-node-method="filterNodeMethod"
+            :props="{ label: 'name' }"
+            :data="areaTree"
+            :render-after-expand="false"
+          />
+        </div>
+      </div>
+      <div class="form">
+        <span class="formSpan">行业:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.hyId"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in industryListAll"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">立项时间:</span>
+        <el-date-picker
+          v-model="lxsjObj"
+          type="daterange"
+          unlink-panels
+          range-separator="To"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        />
+      </div>
+      <div class="form" style="margin-right: 80px">
+        <span class="formSpan">合同:</span>
+        <el-radio-group v-model="queryParams.isSign">
+          <el-radio>全部</el-radio>
+          <el-radio label="1">已签订</el-radio>
+          <el-radio label="0">未签订</el-radio>
+        </el-radio-group>
+      </div>
+      <div class="form">
+        <span class="formSpan">项目状态:</span>
+        <el-radio-group v-model="queryParams.xmzt">
+          <el-radio :label="1">进行中(10)</el-radio>
+          <el-radio :label="4">已验收(7)</el-radio>
+          <el-radio :label="2">已结项(1)</el-radio>
+          <el-radio :label="9">已终止(0)</el-radio>
+          <el-radio>全部(19)</el-radio>
+        </el-radio-group>
+      </div>
+      <div class="from">
+        <div class="btnBox">
+          <el-button type="primary" style="background: #3485ff" @click="searchHandle">
+            <img src="@/assets/imgs/OA/search.png" class="mr-8px" alt="" />
+            查询</el-button
+          >
+          <el-button type="primary">
+            <img src="@/assets/imgs/OA/open.png" class="mr-8px" alt="" />
+            导出</el-button
+          >
+        </div>
+      </div>
+    </div>
+    <div class="infoBox">
+      <ul>
+        <li v-for="(item, index) in infoList" :key="index" class="mr-40px">
+          <img class="mr-8px" :src="getAssetURL(item.icon)" alt="" />
+          <p>{{ item.name }}:</p>
+          <h4 class="font-size-18px">{{ item.num }}</h4>
+        </li>
+      </ul>
+    </div>
+    <div class="tableBox">
+      <div class="table" ref="tableRef">
+        <el-table
+          :data="tableData"
+          style="width: 100%; height: 100%"
+          :style="{ height: tableHeight + 'px' }"
+          :header-cell-style="{
+            background: '#F7F8FA',
+            color: '#121518',
+            height: '50px'
+          }"
+        >
+          <el-table-column label="序号" width="60">
+            <template #default="scope">{{ scope.$index + 1 }}</template>
+          </el-table-column>
+          <el-table-column prop="xmmc" label="项目名称" width="320" />
+          <el-table-column prop="xmbh" label="项目编号" width="180" />
+          <el-table-column prop="xzqmc" label="行政区" width="100" />
+          <el-table-column prop="projectTypeName" label="项目类别" width="120" />
+          <el-table-column prop="zrbm" label="责任部门" />
+          <el-table-column prop="xmjl" label="项目经理" />
+          <el-table-column prop="lxsj" label="立项时间" />
+          <el-table-column prop="yssj" label="验收时间" />
+          <el-table-column prop="outputValue" label="总产值" />
+          <el-table-column prop="xmzt" label="项目状态">
+            <template #default="scope">
+              {{ xmztMap[scope.row.xmzt] }}
+            </template>
+          </el-table-column>
+
+          <el-table-column label="操作" width="80">
+            <template #default="scope">
+              <div class="operateBtn" @click="operateClick(scope.row)">
+                <span>查看</span>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pageBox">
+        <el-pagination
+          v-model:current-page="queryParams.pageNo"
+          :page-size="10"
+          background
+          layout="total, prev, pager, next, jumper"
+          :total="total"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import moment from 'moment'
+import { useRouter } from 'vue-router'
+import request from '@/config/axios'
+import { getAssetURL } from '@/utils/auth'
+import { industryListAll } from '@/utils/business'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+
+defineOptions({ name: 'ProjectBook' })
+const xmztMap: any = { 0: '立项申请中', 1: '进行中', 2: '已结项', 3: '中止' }
+const router = useRouter()
+const { wsCache } = useCache()
+const user = wsCache.get(CACHE_KEY.USER)
+const userId = user.user.id ? user.user.id : ''
+const deptId = user.user.deptId ? user.user.deptId : ''
+const tableRef: any = ref(null)
+const tableHeight: any = ref(0)
+const queryParams = reactive<{
+  xmbh: string
+  xmmc: string
+  xmlbId: string
+  lxsjOn: string
+  lxsjOff: string
+  pageNo: number
+  xzqdm: number | string
+  pageSize: number
+  isSign: any
+  xmzt: any
+  hyId: any
+  deptId: string
+}>({
+  xmbh: '',
+  xmmc: '',
+  xmlbId: '15',
+  lxsjOn: '',
+  lxsjOff: '',
+  pageNo: 1,
+  xzqdm: '',
+  pageSize: 10,
+  isSign: '',
+  xmzt: '',
+  hyId: 0,
+  deptId: deptId
+})
+const lxsjObj = ref()
+const infoList: any = ref([
+  {
+    icon: 'xmzx/xmzcz',
+    name: '项目总产值(元)',
+    num: '0'
+  },
+  {
+    icon: 'xmzx/xmzcb',
+    name: '项目总成本(元)',
+    num: '0'
+  },
+  {
+    icon: 'xmzx/xmzlr',
+    name: '项目总利润(元)',
+    num: '-100000.57'
+  }
+])
+
+const handleCurrentChange = (pageNo: number) => {
+  queryParams.pageNo = pageNo
+  queryProjectListAjax()
+}
+const operateClick = (row: any) => {
+  router.push({
+    path: '/projectDetail',
+    query: { id: row.id }
+  })
+}
+const tableData = ref<Array<any>>([])
+const total = ref<number>()
+const searchHandle: () => void = () => {
+  queryProjectListAjax()
+}
+const queryProjectListAjax = async (): Promise<void> => {
+  const urlApi = `/project/page`
+  if (lxsjObj.value && lxsjObj.value.length > 0) {
+    queryParams.lxsjOn = moment(lxsjObj.value[0]).format('YYYY-MM-DD')
+    queryParams.lxsjOff = moment(lxsjObj.value[1]).format('YYYY-MM-DD')
+  } else {
+    queryParams.lxsjOn = ''
+    queryParams.lxsjOff = ''
+  }
+  const sendData = {
+    ...queryParams,
+    pageSize: 10
+  }
+  if (sendData['hyId'] == 0) {
+    sendData['hyId'] = null
+  }
+  const result = await request.get({ url: urlApi, params: sendData }, '/business')
+  tableData.value = result['records']
+  total.value = result['total']
+}
+queryProjectListAjax()
+
+/**
+ * 获取行政区tree结构数据
+ */
+const areaTree = ref<Array<any>>()
+const filterNodeMethod = (value, data) => {
+  return data.name.includes(value)
+}
+const queryAreaTreeAjax = async (): Promise<void> => {
+  const urlApi = `/system/area/tree`
+  const result = await request.get({ url: urlApi })
+  areaTree.value = result
+}
+queryAreaTreeAjax()
+onMounted(() => {
+  tableHeight.value = tableRef.value.clientHeight
+})
+</script>
+<style lang="scss" scoped>
+@import url(./projectBook.scss);
+</style>

+ 266 - 0
client/src/views/OaSystem/projectCenter/projectBook/myProject.vue

@@ -0,0 +1,266 @@
+<template>
+  <div class="_ProjectCenterBook">
+    <div class="searchBox">
+      <div class="form">
+        <span class="formSpan">项目名称:</span>
+        <el-input v-model="queryParams.xmmc" placeholder="请输入项目名称" style="width: 210px" />
+      </div>
+      <div class="form">
+        <span class="formSpan">项目编号:</span>
+        <el-input v-model="queryParams.xmbh" placeholder="请输入项目名称" style="width: 160px" />
+      </div>
+      <div class="form">
+        <span class="formSpan">行政区:</span>
+        <div style="width: 160px">
+          <el-tree-select
+            v-model="queryParams.xzqdm"
+            node-key="id"
+            check-strictly
+            filterable
+            :filter-node-method="filterNodeMethod"
+            :props="{ label: 'name' }"
+            :data="areaTree"
+            :render-after-expand="false"
+          />
+        </div>
+      </div>
+      <div class="form">
+        <span class="formSpan">行业:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.hyId"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in industryListAll"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">立项时间:</span>
+        <el-date-picker
+          v-model="lxsjObj"
+          type="daterange"
+          unlink-panels
+          range-separator="To"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        />
+      </div>
+      <div class="form" style="margin-right: 80px">
+        <span class="formSpan">合同:</span>
+        <el-radio-group v-model="queryParams.isSign">
+          <el-radio>全部</el-radio>
+          <el-radio label="1">已签订</el-radio>
+          <el-radio label="0">未签订</el-radio>
+        </el-radio-group>
+      </div>
+      <div class="form">
+        <span class="formSpan">项目状态:</span>
+        <el-radio-group v-model="queryParams.xmzt">
+          <el-radio :label="1">进行中(10)</el-radio>
+          <el-radio :label="4">已验收(7)</el-radio>
+          <el-radio :label="2">已结项(1)</el-radio>
+          <el-radio :label="9">已终止(0)</el-radio>
+          <el-radio>全部(19)</el-radio>
+        </el-radio-group>
+      </div>
+      <div class="from">
+        <div class="btnBox">
+          <el-button type="primary" style="background: #3485ff" @click="searchHandle">
+            <img src="@/assets/imgs/OA/search.png" class="mr-8px" alt="" />
+            查询</el-button
+          >
+          <el-button type="primary">
+            <img src="@/assets/imgs/OA/open.png" class="mr-8px" alt="" />
+            导出</el-button
+          >
+        </div>
+      </div>
+    </div>
+    <div class="infoBox">
+      <ul>
+        <li v-for="(item, index) in infoList" :key="index" class="mr-40px">
+          <img class="mr-8px" :src="getAssetURL(item.icon)" alt="" />
+          <p>{{ item.name }}:</p>
+          <h4 class="font-size-18px">{{ item.num }}</h4>
+        </li>
+      </ul>
+    </div>
+    <div class="tableBox">
+      <div class="table" ref="tableRef">
+        <el-table
+          :data="tableData"
+          style="width: 100%; height: 100%"
+          :style="{ height: tableHeight + 'px' }"
+          :header-cell-style="{
+            background: '#F7F8FA',
+            color: '#121518',
+            height: '50px'
+          }"
+        >
+          <el-table-column label="序号" width="60">
+            <template #default="scope">{{ scope.$index + 1 }}</template>
+          </el-table-column>
+          <el-table-column prop="xmmc" label="项目名称" width="320" />
+          <el-table-column prop="xmbh" label="项目编号" width="180" />
+          <el-table-column prop="xzqmc" label="行政区" width="100" />
+          <el-table-column prop="projectTypeName" label="项目类别" width="120" />
+          <el-table-column prop="zrbm" label="责任部门" />
+          <el-table-column prop="xmjl" label="项目经理" />
+          <el-table-column prop="lxsj" label="立项时间" />
+          <el-table-column prop="yssj" label="验收时间" />
+          <el-table-column prop="outputValue" label="总产值" />
+          <el-table-column prop="xmzt" label="项目状态">
+            <template #default="scope">
+              {{ xmztMap[scope.row.xmzt] }}
+            </template>
+          </el-table-column>
+
+          <el-table-column label="操作" width="80">
+            <template #default="scope">
+              <div class="operateBtn" @click="operateClick(scope.row)">
+                <span>查看</span>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pageBox">
+        <el-pagination
+          v-model:current-page="queryParams.pageNo"
+          :page-size="10"
+          background
+          layout="total, prev, pager, next, jumper"
+          :total="total"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import moment from 'moment'
+import { useRouter } from 'vue-router'
+import request from '@/config/axios'
+import { getAssetURL } from '@/utils/auth'
+import { industryListAll } from '@/utils/business'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+
+defineOptions({ name: 'ProjectBook' })
+const xmztMap: any = { 0: '立项申请中', 1: '进行中', 2: '已结项', 3: '中止' }
+const router = useRouter()
+const { wsCache } = useCache()
+const user = wsCache.get(CACHE_KEY.USER)
+const userId = user.user.id ? user.user.id : ''
+const deptId = user.user.deptId ? user.user.deptId : ''
+const tableRef: any = ref(null)
+const tableHeight: any = ref(0)
+const queryParams = reactive<{
+  xmbh: string
+  xmmc: string
+  xmlbId: string
+  lxsjOn: string
+  lxsjOff: string
+  pageNo: number
+  xzqdm: number | string
+  pageSize: number
+  isSign: any
+  xmzt: any
+  hyId: any
+  userId: string
+}>({
+  xmbh: '',
+  xmmc: '',
+  xmlbId: '15',
+  lxsjOn: '',
+  lxsjOff: '',
+  pageNo: 1,
+  xzqdm: '',
+  pageSize: 10,
+  isSign: '',
+  xmzt: '',
+  hyId: 0,
+  userId: userId
+})
+const lxsjObj = ref()
+const infoList: any = ref([
+  {
+    icon: 'xmzx/xmzcz',
+    name: '项目总产值(元)',
+    num: '0'
+  },
+  {
+    icon: 'xmzx/xmzcb',
+    name: '项目总成本(元)',
+    num: '0'
+  },
+  {
+    icon: 'xmzx/xmzlr',
+    name: '项目总利润(元)',
+    num: '-100000.57'
+  }
+])
+
+const handleCurrentChange = (pageNo: number) => {
+  queryParams.pageNo = pageNo
+  queryProjectListAjax()
+}
+const operateClick = (row: any) => {
+  router.push({
+    path: '/projectDetail',
+    query: { id: row.id }
+  })
+}
+const tableData = ref<Array<any>>([])
+const total = ref<number>()
+const searchHandle: () => void = () => {
+  queryProjectListAjax()
+}
+const queryProjectListAjax = async (): Promise<void> => {
+  const urlApi = `/project/page`
+  if (lxsjObj.value && lxsjObj.value.length > 0) {
+    queryParams.lxsjOn = moment(lxsjObj.value[0]).format('YYYY-MM-DD')
+    queryParams.lxsjOff = moment(lxsjObj.value[1]).format('YYYY-MM-DD')
+  } else {
+    queryParams.lxsjOn = ''
+    queryParams.lxsjOff = ''
+  }
+  const sendData = {
+    ...queryParams,
+    pageSize: 10
+  }
+  if (sendData['hyId'] == 0) {
+    sendData['hyId'] = null
+  }
+  const result = await request.get({ url: urlApi, params: sendData }, '/business')
+  tableData.value = result['records']
+  total.value = result['total']
+}
+queryProjectListAjax()
+
+/**
+ * 获取行政区tree结构数据
+ */
+const areaTree = ref<Array<any>>()
+const filterNodeMethod = (value, data) => {
+  return data.name.includes(value)
+}
+const queryAreaTreeAjax = async (): Promise<void> => {
+  const urlApi = `/system/area/tree`
+  const result = await request.get({ url: urlApi })
+  areaTree.value = result
+}
+queryAreaTreeAjax()
+onMounted(() => {
+  tableHeight.value = tableRef.value.clientHeight
+})
+</script>
+<style lang="scss" scoped>
+@import url(./projectBook.scss);
+</style>

+ 315 - 0
client/src/views/OaSystem/projectCenter/purchaseContract/deptContract.vue

@@ -0,0 +1,315 @@
+<template>
+  <div class="_PurchaseContractBox">
+    <div class="searchBox">
+      <div class="form">
+        <span class="formSpan">合同名称:</span>
+        <el-input v-model="queryParams.name" placeholder="请输入合同名称" style="width: 210px" />
+      </div>
+      <div class="form">
+        <span class="formSpan">合同编号:</span>
+        <el-input
+          v-model="queryParams.contractNumber"
+          placeholder="请输入合同编号"
+          style="width: 160px"
+        />
+      </div>
+      <div class="form">
+        <span class="formSpan">签订状态:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.isSign"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in isSignListAll"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">签订方式:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.signWay"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in signWayAllList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">合同主类型:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.mainType"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in mainTypeAllList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">合同次类型:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.secondType"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in secondTypeAllList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">拿回时间:</span>
+        <el-date-picker
+          v-model="lxsjObj"
+          type="daterange"
+          unlink-panels
+          range-separator="To"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        />
+      </div>
+      <div class="from">
+        <div class="btnBox">
+          <el-button type="primary" style="background: #3485ff" @click="searchHandle">
+            <img src="@/assets/imgs/OA/search.png" class="mr-8px" alt="" />
+            查询</el-button
+          >
+          <el-button type="primary">
+            <img src="@/assets/imgs/OA/open.png" class="mr-8px" alt="" />
+            导出</el-button
+          >
+        </div>
+      </div>
+    </div>
+    <div class="infoBox">
+      <ul>
+        <li v-for="(item, index) in infoList" :key="index" class="mr-40px">
+          <img class="mr-8px" :src="getAssetURL(item.icon)" alt="" />
+          <p>{{ item.name }}:</p>
+          <h4 class="font-size-18px">{{ item.num }}</h4>
+        </li>
+      </ul>
+    </div>
+    <div class="tableBox">
+      <div class="table" ref="tableRef">
+        <el-table
+          :data="tableData"
+          style="width: 100%; height: 100%"
+          :style="{ height: tableHeight + 'px' }"
+          :header-cell-style="{
+            background: '#F7F8FA',
+            color: '#121518',
+            height: '50px'
+          }"
+        >
+          <el-table-column label="序号" width="60">
+            <template #default="scope">{{ scope.$index + 1 }}</template>
+          </el-table-column>
+          <el-table-column prop="contractNumber" label="合同编号" width="180" />
+          <el-table-column prop="name" label="合同名称" width="240" />
+          <el-table-column prop="isSign" label="签订状态" width="100">
+            <template #default="scope">
+              {{ isSignMap[scope.row.isSign] }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="areaManager" label="区域经理" width="120" />
+          <el-table-column prop="clientName" label="委托方" width="180" />
+          <el-table-column prop="mainType" label="合同主类型" width="80">
+            <template #default="scope">
+              {{ mainTypeMap[scope.row.mainType] }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="amountStatus" label="合同状态" width="80">
+            <template #default="scope">
+              {{ amountStatusMap[scope.row.amountStatus] }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="contractAmount" label="合同金额" width="100" />
+          <el-table-column prop="contractAmount" label="已回款金额" width="100" />
+          <el-table-column prop="receivableAmount" label="应收账款" width="100" />
+          <el-table-column prop="contractBalance" label="合同余额" width="100" />
+          <el-table-column prop="contractOn" label="拿出日期" width="120" />
+          <el-table-column prop="contractOff" label="拿回日期" width="120" />
+          <el-table-column label="操作" width="80">
+            <template #default="scope">
+              <div class="operateBtn" @click="operateClick(scope.row)">
+                <span>查看</span>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pageBox">
+        <el-pagination
+          v-model:current-page="queryParams.pageNo"
+          :page-size="10"
+          background
+          layout="total, prev, pager, next, jumper"
+          :total="total"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import moment from 'moment'
+import { useRouter } from 'vue-router'
+import request from '@/config/axios'
+import { getAssetURL } from '@/utils/auth'
+import { isSignListAll } from '@/utils/business'
+import { signWayAllList } from '@/utils/business'
+import { mainTypeAllList } from '@/utils/business'
+import { secondTypeAllList } from '@/utils/business'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+
+defineOptions({ name: 'ProjectBook' })
+const amountStatusMap: any = { 2: '未付清', 3: '已付清', 4: '手动设置已付清' }
+const signWayMap: any = { 1: '跟单', 2: '半开拓', 3: '开拓' }
+const isSignMap: any = { 0: '未签', 1: '已签', 2: '待拿回', 3: '不签' }
+const mainTypeMap: any = { 1: '规划类', 2: '数据工程类', 3: '软件类', 4: '采购类' }
+const secondTypeMap: any = {
+  1: '普通',
+  2: '技贸',
+  3: '入围',
+  4: '补充协议/变更',
+  5: '分包',
+  6: '外包',
+  7: '采购'
+}
+const router = useRouter()
+const { wsCache } = useCache()
+const tableRef: any = ref(null)
+const tableHeight: any = ref(0)
+const user = wsCache.get(CACHE_KEY.USER)
+const userId = user.user.id ? user.user.id : ''
+const deptId = user.user.deptId ? user.user.deptId : ''
+const queryParams = reactive<{
+  contractNumber: string
+  name: string
+  pageNo: number
+  pageSize: number
+  isSign: any
+  signWay: any
+  mainType: any
+  secondType: any
+  contractOn: string
+  contractOff: string
+  deptId: string
+}>({
+  contractNumber: '',
+  name: '',
+  pageNo: 1,
+  pageSize: 10,
+  isSign: '',
+  signWay: '',
+  mainType: '',
+  secondType: '',
+  contractOn: '',
+  contractOff: '',
+  deptId: deptId
+})
+const lxsjObj = ref()
+const infoList: any = ref([
+  {
+    icon: 'xmzx/xmzcz',
+    name: '总合同金额(万元)',
+    num: '0'
+  },
+  {
+    icon: 'xmzx/xmzcb',
+    name: '总开票金额(万元)',
+    num: '0'
+  },
+  {
+    icon: 'xmzx/xmzlr',
+    name: '总回款金额(万元)',
+    num: '-100000.57'
+  },
+  {
+    icon: 'xmzx/xmzlr',
+    name: '总应收款(万元)',
+    num: '-100000.57'
+  },
+  {
+    icon: 'xmzx/xmzlr',
+    name: '总合同余额(万元)',
+    num: '-100000.57'
+  }
+])
+
+const handleCurrentChange = (pageNo: number) => {
+  queryParams.pageNo = pageNo
+  queryContractListAjax()
+}
+const operateClick = (row: any) => {
+  router.push({
+    path: '/projectDetail',
+    query: { id: row.projectId, contractId: row.id }
+  })
+}
+const tableData = ref<Array<any>>([])
+const total = ref<number>()
+const searchHandle: () => void = () => {
+  queryContractListAjax()
+}
+const queryContractListAjax = async (): Promise<void> => {
+  const urlApi = `/contract/page`
+  if (lxsjObj.value && lxsjObj.value.length > 0) {
+    queryParams.contractOn = moment(lxsjObj.value[0]).format('YYYY-MM-DD')
+    queryParams.contractOff = moment(lxsjObj.value[1]).format('YYYY-MM-DD')
+  }
+  const sendData = {
+    ...queryParams,
+    pageSize: 10
+  }
+  const result = await request.get({ url: urlApi, params: sendData }, 'http://localhost:6010')
+  tableData.value = result['records']
+  total.value = result['total']
+}
+debugger
+queryContractListAjax()
+
+const filterNodeMethod = (value, data) => {
+  return data.name.includes(value)
+}
+onMounted(() => {
+  tableHeight.value = tableRef.value.clientHeight
+})
+</script>
+<style lang="scss" scoped>
+@import url(./purchaseContract.scss);
+.purchaseContractBox {
+  margin-top: 20px;
+  height: calc(100% - 20px);
+  background-color: #fff;
+  border-radius: 20px;
+  padding: 20px;
+  position: relative;
+  text-align: center;
+}
+</style>

+ 314 - 0
client/src/views/OaSystem/projectCenter/purchaseContract/myContract.vue

@@ -0,0 +1,314 @@
+<template>
+  <div class="_PurchaseContractBox">
+    <div class="searchBox">
+      <div class="form">
+        <span class="formSpan">合同名称:</span>
+        <el-input v-model="queryParams.name" placeholder="请输入合同名称" style="width: 210px" />
+      </div>
+      <div class="form">
+        <span class="formSpan">合同编号:</span>
+        <el-input
+          v-model="queryParams.contractNumber"
+          placeholder="请输入合同编号"
+          style="width: 160px"
+        />
+      </div>
+      <div class="form">
+        <span class="formSpan">签订状态:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.isSign"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in isSignListAll"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">签订方式:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.signWay"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in signWayAllList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">合同主类型:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.mainType"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in mainTypeAllList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">合同次类型:</span>
+        <el-select
+          width="160px"
+          v-model="queryParams.secondType"
+          class="m-2"
+          placeholder="请选择行业"
+          size="large"
+        >
+          <el-option
+            v-for="item in secondTypeAllList"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </div>
+      <div class="form">
+        <span class="formSpan">拿回时间:</span>
+        <el-date-picker
+          v-model="lxsjObj"
+          type="daterange"
+          unlink-panels
+          range-separator="To"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        />
+      </div>
+      <div class="from">
+        <div class="btnBox">
+          <el-button type="primary" style="background: #3485ff" @click="searchHandle">
+            <img src="@/assets/imgs/OA/search.png" class="mr-8px" alt="" />
+            查询</el-button
+          >
+          <el-button type="primary">
+            <img src="@/assets/imgs/OA/open.png" class="mr-8px" alt="" />
+            导出</el-button
+          >
+        </div>
+      </div>
+    </div>
+    <div class="infoBox">
+      <ul>
+        <li v-for="(item, index) in infoList" :key="index" class="mr-40px">
+          <img class="mr-8px" :src="getAssetURL(item.icon)" alt="" />
+          <p>{{ item.name }}:</p>
+          <h4 class="font-size-18px">{{ item.num }}</h4>
+        </li>
+      </ul>
+    </div>
+    <div class="tableBox">
+      <div class="table" ref="tableRef">
+        <el-table
+          :data="tableData"
+          style="width: 100%; height: 100%"
+          :style="{ height: tableHeight + 'px' }"
+          :header-cell-style="{
+            background: '#F7F8FA',
+            color: '#121518',
+            height: '50px'
+          }"
+        >
+          <el-table-column label="序号" width="60">
+            <template #default="scope">{{ scope.$index + 1 }}</template>
+          </el-table-column>
+          <el-table-column prop="contractNumber" label="合同编号" width="180" />
+          <el-table-column prop="name" label="合同名称" width="240" />
+          <el-table-column prop="isSign" label="签订状态" width="100">
+            <template #default="scope">
+              {{ isSignMap[scope.row.isSign] }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="areaManager" label="区域经理" width="120" />
+          <el-table-column prop="clientName" label="委托方" width="180" />
+          <el-table-column prop="mainType" label="合同主类型" width="80">
+            <template #default="scope">
+              {{ mainTypeMap[scope.row.mainType] }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="amountStatus" label="合同状态" width="80">
+            <template #default="scope">
+              {{ amountStatusMap[scope.row.amountStatus] }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="contractAmount" label="合同金额" width="100" />
+          <el-table-column prop="contractAmount" label="已回款金额" width="100" />
+          <el-table-column prop="receivableAmount" label="应收账款" width="100" />
+          <el-table-column prop="contractBalance" label="合同余额" width="100" />
+          <el-table-column prop="contractOn" label="拿出日期" width="120" />
+          <el-table-column prop="contractOff" label="拿回日期" width="120" />
+          <el-table-column label="操作" width="80">
+            <template #default="scope">
+              <div class="operateBtn" @click="operateClick(scope.row)">
+                <span>查看</span>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pageBox">
+        <el-pagination
+          v-model:current-page="queryParams.pageNo"
+          :page-size="10"
+          background
+          layout="total, prev, pager, next, jumper"
+          :total="total"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+<script setup lang="ts">
+import moment from 'moment'
+import { useRouter } from 'vue-router'
+import request from '@/config/axios'
+import { getAssetURL } from '@/utils/auth'
+import { isSignListAll } from '@/utils/business'
+import { signWayAllList } from '@/utils/business'
+import { mainTypeAllList } from '@/utils/business'
+import { secondTypeAllList } from '@/utils/business'
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+
+defineOptions({ name: 'ProjectBook' })
+const amountStatusMap: any = { 2: '未付清', 3: '已付清', 4: '手动设置已付清' }
+const signWayMap: any = { 1: '跟单', 2: '半开拓', 3: '开拓' }
+const isSignMap: any = { 0: '未签', 1: '已签', 2: '待拿回', 3: '不签' }
+const mainTypeMap: any = { 1: '规划类', 2: '数据工程类', 3: '软件类', 4: '采购类' }
+const secondTypeMap: any = {
+  1: '普通',
+  2: '技贸',
+  3: '入围',
+  4: '补充协议/变更',
+  5: '分包',
+  6: '外包',
+  7: '采购'
+}
+const router = useRouter()
+const { wsCache } = useCache()
+const user = wsCache.get(CACHE_KEY.USER)
+const userId = user.user.id ? user.user.id : ''
+const deptId = user.user.deptId ? user.user.deptId : ''
+const tableRef: any = ref(null)
+const tableHeight: any = ref(0)
+const queryParams = reactive<{
+  contractNumber: string
+  name: string
+  pageNo: number
+  pageSize: number
+  isSign: any
+  signWay: any
+  mainType: any
+  secondType: any
+  contractOn: string
+  contractOff: string
+  managerId: string
+}>({
+  contractNumber: '',
+  name: '',
+  pageNo: 1,
+  pageSize: 10,
+  isSign: '',
+  signWay: '',
+  mainType: '',
+  secondType: '',
+  contractOn: '',
+  contractOff: '',
+  managerId: userId
+})
+const lxsjObj = ref()
+const infoList: any = ref([
+  {
+    icon: 'xmzx/xmzcz',
+    name: '总合同金额(万元)',
+    num: '0'
+  },
+  {
+    icon: 'xmzx/xmzcb',
+    name: '总开票金额(万元)',
+    num: '0'
+  },
+  {
+    icon: 'xmzx/xmzlr',
+    name: '总回款金额(万元)',
+    num: '-100000.57'
+  },
+  {
+    icon: 'xmzx/xmzlr',
+    name: '总应收款(万元)',
+    num: '-100000.57'
+  },
+  {
+    icon: 'xmzx/xmzlr',
+    name: '总合同余额(万元)',
+    num: '-100000.57'
+  }
+])
+
+const handleCurrentChange = (pageNo: number) => {
+  queryParams.pageNo = pageNo
+  queryContractListAjax()
+}
+const operateClick = (row: any) => {
+  router.push({
+    path: '/projectDetail',
+    query: { id: row.projectId, contractId: row.id }
+  })
+}
+const tableData = ref<Array<any>>([])
+const total = ref<number>()
+const searchHandle: () => void = () => {
+  queryContractListAjax()
+}
+const queryContractListAjax = async (): Promise<void> => {
+  const urlApi = `/contract/page`
+  if (lxsjObj.value && lxsjObj.value.length > 0) {
+    queryParams.contractOn = moment(lxsjObj.value[0]).format('YYYY-MM-DD')
+    queryParams.contractOff = moment(lxsjObj.value[1]).format('YYYY-MM-DD')
+  }
+  const sendData = {
+    ...queryParams,
+    pageSize: 10
+  }
+  const result = await request.get({ url: urlApi, params: sendData }, 'http://localhost:6010')
+  tableData.value = result['records']
+  total.value = result['total']
+}
+queryContractListAjax()
+
+const filterNodeMethod = (value, data) => {
+  return data.name.includes(value)
+}
+onMounted(() => {
+  tableHeight.value = tableRef.value.clientHeight
+})
+</script>
+<style lang="scss" scoped>
+@import url(./purchaseContract.scss);
+.purchaseContractBox {
+  margin-top: 20px;
+  height: calc(100% - 20px);
+  background-color: #fff;
+  border-radius: 20px;
+  padding: 20px;
+  position: relative;
+  text-align: center;
+}
+</style>

+ 98 - 0
client/src/views/OaSystem/projectCenter/purchaseContract/purchaseContract.scss

@@ -0,0 +1,98 @@
+._PurchaseContractBox {
+  width: calc(100% - 30px);
+  height: calc(100% - 30px);
+  background: #FFFFFF;
+  border-radius: 4px 4px 4px 4px;
+  border: 1px solid #DEE0E3;
+  margin: 15px;
+
+  .searchBox {
+    width: 100%;
+    height: 125px;
+    background: #F7F8FA;
+    border-radius: 4px 4px 0 0;
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+    padding: 0 20px;
+    box-sizing: border-box;
+
+    .form {
+      display: flex;
+      align-items: center;
+      margin-right: 20px;
+
+      .formSpan {
+        font-size: 16px;
+      }
+
+      .btnBox {
+        display: flex;
+        align-items: center;
+      }
+    }
+  }
+
+  .infoBox {
+    width: 100%;
+    height: 55px;
+    background: #EDF2FB;
+
+    ul {
+      width: 100%;
+      height: 100%;
+      display: flex;
+      align-items: center;
+      padding: 0 20px;
+
+      li {
+        list-style: none;
+        display: flex;
+        align-items: center;
+      }
+    }
+  }
+
+  .tableBox {
+    width: 100%;
+    height: calc(100% - 180px);
+    padding: 15px 20px;
+    position: relative;
+
+    .table {
+      width: 100%;
+      height: calc(100% - 40px);
+
+      .operateBtn {
+        width: 54px;
+        height: 24px;
+        background: #EBF2FF;
+        border-radius: 16px 16px 16px 16px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        cursor: pointer;
+
+        span {
+          color: #2E77E6;
+        }
+      }
+    }
+
+    .pageBox {
+      position: absolute;
+      right: 20px;
+      bottom: 10px;
+      text-align: right;
+    }
+  }
+  :deep(.el-radio__label),
+  :deep(.el-checkbox__label){
+      font-size: 16px;
+  }
+  :deep(.el-radio-group){
+    label {
+      margin-right: 10px;
+    }
+  }
+}