浏览代码

fix:支撑管理-档案库管理

liqh 4 月之前
父节点
当前提交
d4b42565b9

+ 8 - 0
src/views/support-manage/Archive/project-archive/archive-detail/components/ArchiveTree/department-mitt.js

@@ -0,0 +1,8 @@
+/*
+ * 部门event bus
+ *
+ * @Author:    DCCloud
+ * @Date:      2022-07-12 23:32:48
+ */
+import mitt from 'mitt';
+export default mitt();

+ 54 - 0
src/views/support-manage/Archive/project-archive/archive-detail/components/ArchiveTree/index.vue

@@ -0,0 +1,54 @@
+<!--
+  * 组织架构
+  *
+  * @Author:    DCCloud
+  * @Date:      2022-08-08 20:46:18
+-->
+<template>
+  <div class="height100">
+    <a-row :gutter="24" class="height100">
+      <a-col :span="5">
+        <FilesTree ref="rulesTreeRef" />
+      </a-col>
+
+      <a-col :span="19" class="height100">
+        <div class="employee-box height100">
+          <FilesList style="flex-grow: 2.5" class="employee" :selectedRulesId="selectedRulesId" />
+        </div>
+      </a-col>
+    </a-row>
+  </div>
+</template>
+<script setup>
+import _ from 'lodash';
+import { computed, ref } from 'vue';
+import FilesTree from './modules/file-tree/index.vue';
+import FilesList from './modules/file-list/index.vue';
+
+const rulesTreeRef = ref();
+
+// 当前选中的目录id
+const selectedRulesId = computed(() => {
+  if (rulesTreeRef.value) {
+    let selectedKeys = rulesTreeRef.value.selectedKeys;
+    console.log("selectedDepartmentId", _.isEmpty(selectedKeys) ? '' : selectedKeys[0]);
+    return _.isEmpty(selectedKeys) ? '' : selectedKeys[0];
+  }
+  return '';
+});
+
+</script>
+<style scoped lang="less">
+.height100 {
+  height: 100%;
+}
+
+.employee-box {
+  display: flex;
+  flex-direction: column;
+
+  .employee {
+    flex-grow: 2;
+  }
+}
+</style>

+ 146 - 0
src/views/support-manage/Archive/project-archive/archive-detail/components/ArchiveTree/modules/file-detail/index.vue

@@ -0,0 +1,146 @@
+<!--
+  * 部门表单 弹窗
+  *
+  * @Author:    BoundLink
+  * @Date:      2022-08-08 20:46:18
+-->
+<template>
+  <a-modal v-model:open="visible" width="40%" title="文件登记" @ok="onSubmit" @cancel="closeModal" destroyOnClose>
+    <a-form class="smart-query-form" ref="formRef" labelWrap :label-col="labelCol" :model="form" :rules="rules">
+      <div class="cost-compose">
+        <div class="basic-info">
+          <div class="basic-info-form">
+            <a-row :gutter="16" class="smart-query-form-row">
+              <a-col :span="24">
+                <a-form-item label="文件类别" name="fileType" class="smart-query-form-item">
+                  <DictSelect key-code="BLINK_CUSTOMER_FILE_TYPE" v-model:value="form.fileType" placeholder="请选择文件类别" width="100%" />
+                </a-form-item>
+              </a-col>
+            </a-row>
+            <a-row :gutter="16" class="smart-query-form-row">
+              <a-col :span="24">
+                <a-form-item label="备注" name="remark" class="smart-query-form-item">
+                  <a-textarea v-model:value="form.remark" placeholder="请输入备注" :auto-size="{ minRows: 2, maxRows: 5 }" />
+                </a-form-item>
+              </a-col>
+            </a-row>
+            <a-row :gutter="16" class="smart-query-form-row">
+              <a-col :span="24">
+                <a-form-item label="文件" name="form.attachment" class="smart-query-form-item">
+                  <Upload
+                    ref="UploadRef"
+                    :defaultFileList="defaultFileList"
+                    :maxUploadSize="10"
+                    :folder="FILE_FOLDER_TYPE_ENUM.COMMON.value"
+                    buttonText="上传文件"
+                    listType="text"
+                    extraMsg="最多上传10个附件"
+                    @change="changeAttachment"
+                  />
+                </a-form-item>
+              </a-col>
+            </a-row>
+          </div>
+        </div>
+      </div>
+    </a-form>
+  </a-modal>
+</template>
+<script setup>
+  import { reactive, ref } from 'vue';
+  import { theme, message, Modal } from 'ant-design-vue';
+  import _ from 'lodash';
+  import DictSelect from '/@/components/support/dict-select/index.vue';
+  import Upload from '/@/components/support/file-upload/index.vue';
+  import { clientManageApi } from '/@/api/market-manage/index.js';
+  import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';
+
+  // ----------------------- 对外暴漏 ---------------------
+  defineExpose({
+    showModal,
+  });
+
+  // ----------------------- modal 的显示与隐藏 ---------------------
+
+  const labelCol = { style: { width: '70px' } };
+  const emits = defineEmits(['refreshTable']);
+  const visible = ref(false);
+  const UploadRef = ref();
+  function showModal(params) {
+    visible.value = true;
+    form.bizId = params;
+  }
+
+  function closeModal() {
+    UploadRef.value.clear();
+    visible.value = false;
+    resetFormData();
+  }
+
+  // ----------------------- form 表单操作 ---------------------
+  const formRef = ref();
+
+  const formDefault = {
+    bizId: undefined, // 项目id
+    fileType: undefined, // 文件类别
+    remark: undefined, //备注
+    attachment: undefined, // 文件
+    bizModule: 'customer',//标记 文件来源
+  };
+
+  let form = reactive({
+    ...formDefault,
+  });
+
+  // 表单校验规则
+  const fromRules = {
+    // decisionName: [{ required: true, message: '决策人姓名不能为空' }],
+  };
+
+  // 重置表单数据
+  function resetFormData() {
+    Object.assign(form, formDefault);
+  }
+
+  // ----------------------- 上传附件 ----------------------------
+  // 已上传的附件列表
+  const defaultFileList = ref([]);
+  function changeAttachment(fileList) {
+    defaultFileList.value = fileList;
+    form.attachment = _.isEmpty(fileList) ? [] : fileList;
+  }
+
+  // ----------------------- form 表单  ajax 操作 ---------------------
+  function onSubmit() {
+    console.log('form', form);
+    formRef.value
+      .validateFields()
+      .then((values) => {
+        Modal.confirm({
+          title: '提示',
+          content: '确定要提交吗?',
+          okText: '确认',
+          onOk() {
+            postFileData();
+          },
+          cancelText: '取消',
+          onCancel() {},
+        });
+      })
+      .catch((error) => {
+        console.log('step1_error', error);
+      });
+  }
+
+  const postFileData = async () => {
+    await clientManageApi.FileAddition(form);
+    message.success('提交成功');
+    emits('refreshTable');
+    onClose();
+  };
+
+  function onClose() {
+    Object.assign(form, formDefault);
+    visible.value = false;
+  }
+</script>

+ 210 - 0
src/views/support-manage/Archive/project-archive/archive-detail/components/ArchiveTree/modules/file-list/index.vue

@@ -0,0 +1,210 @@
+<template>
+  <div class="table-demo">
+    <bs-table v-bind="tableOptions">
+      <template #toolbarLeft>
+        <a-space>
+          <a-button type="primary" @click="goDetailPage">
+            <template #icon>
+              <PlusOutlined />
+            </template>
+            <span>上传文件</span>
+          </a-button>
+        </a-space>
+      </template>
+    </bs-table>
+  </div>
+  <fileDetail ref="fileDetailRef" @refreshTable="refreshTable()" />
+</template>
+
+<script setup lang="jsx">
+  import BsTable, { useBsTable } from '/@/components/BsUi/Table/index.js';
+  import { onMounted, ref, watch } from 'vue';
+  import { useRouter } from 'vue-router';
+  import { DISPLAY_STATE } from '/@/components/BsUi/constant.js';
+  import fileDetail from '/@/views/support-manage/Archive/project-archive/archive-detail/components/ArchiveTree/modules/file-detail/index.vue';
+
+  const props = defineProps({
+    selectedRulesId: String,
+  });
+
+  const router = useRouter();
+  const query = router.currentRoute.value.query;
+
+  const fileDetailRef = ref();
+
+  const {
+    tableOptions,
+    fetchTableData,
+    setTablePropsValue: setValue,
+    getTablePropsValue: getValue,
+  } = useBsTable({
+    tableOptions: {
+      url: '/supports/risk/rule/queryPage',
+      gridOptions: {
+        loading: false,
+        columns: [
+          {
+            type: 'seq',
+            align: 'center',
+          },
+          {
+            title: '风险维度',
+            field: 'riskDimension',
+            ellipsis: true,
+            formatter: ({ cellValue }) => {
+              return cellValue && cellValue.length > 0 ? cellValue[0].valueName : '';
+            },
+          },
+          {
+            title: '风险模板',
+            // field: 'riskModel',
+            ellipsis: true,
+            slots: {
+              default({ row, column }) {
+                return <span>{row?.riskModel?.[0].valueName}</span>;
+              },
+            },
+          },
+          {
+            title: '风险等级',
+            field: 'riskGrade',
+            ellipsis: true,
+          },
+          {
+            title: '风险指标',
+            field: 'riskMetrics',
+            ellipsis: true,
+          },
+          {
+            title: '指标定义',
+            field: 'definedMetrics',
+            ellipsis: true,
+          },
+          {
+            title: '条件运算符',
+            field: 'operator',
+            ellipsis: true,
+          },
+          {
+            // fixed: 'right',
+            align: 'center',
+            cellRender: {
+              name: 'CellOption',
+              extraProps: {
+                buttons: [
+                  {
+                    title: '预览',
+                    code: 'view',
+                    display: ({ row }) => {
+                      return DISPLAY_STATE.VISIBLE;
+                    },
+                    disabled({ row }) {
+                      return false;
+                    },
+                    onClick({ row }) {
+                      filePreviewModalRef.value.showPreview(row.attachment[0]);
+                    },
+                    extraProps: {},
+                  },
+                  {
+                    title: '下载',
+                    code: 'edit',
+                    display: ({ row }) => {
+                      return DISPLAY_STATE.VISIBLE;
+                    },
+                    disabled({ row }) {
+                      return false;
+                    },
+                    onClick({ row }) {
+                      fileApi.downLoadFile(row.attachment[0].fileKey);
+                    },
+                    extraProps: {},
+                  },
+                  {
+                    title: '删除',
+                    code: 'delete',
+                    display: ({ row }) => {
+                      return DISPLAY_STATE.VISIBLE;
+                    },
+                    disabled({ row }) {
+                      return false;
+                    },
+                    onClick({ row }) {
+                      Modal.confirm({
+                        title: '提示',
+                        content: `移除后该数据将不在列表展示,确认移除该数据吗?`,
+                        onOk: () => {
+                          deleteFile(row.id).then((res) => {
+                            if (res.ok) {
+                              message.success('移除成功');
+                              fetchTableData();
+                            }
+                          });
+                        },
+                      });
+                    },
+                    extraProps: {
+                      danger: true,
+                    },
+                  },
+                ],
+              },
+            },
+          },
+        ],
+        data: [
+          {
+            id: 1,
+            name: '测试数据',
+            dictField: [
+              {
+                dictKeyId: '',
+                dictValueId: '',
+                remark: '',
+                sort: 3,
+                status: 1,
+                valueCode: '03',
+                valueName: '微信公众号',
+              },
+            ],
+          },
+        ], // 模拟数据源
+      },
+      pagerConfig: {
+        enabled: true,
+        pageSize: 10,
+        pageNum: 1,
+      },
+      toolbarConfig: {},
+      tableSearchBeforeBiz() {
+        const searchParams = getValue('searchConfig.data');
+        setValue('searchConfig.data', { ...searchParams, key: props.selectedRulesId });
+      },
+    },
+  });
+
+  function goDetailPage(record) {
+    console.log('record', record);
+    fileDetailRef.value.showModal();
+  }
+
+  // 监听 selectedRulesId 的变化
+  watch(
+    () => props.selectedRulesId,
+    (newVal, oldVal) => {
+      if (newVal !== oldVal) {
+        fetchTableData(newVal);
+      }
+    },
+    { immediate: true }
+  );
+
+  onMounted(() => {
+    console.log('表格已加载');
+  });
+</script>
+
+<style scoped lang="scss">
+  .table-demo {
+  }
+</style>

+ 262 - 0
src/views/support-manage/Archive/project-archive/archive-detail/components/ArchiveTree/modules/file-tree/index.vue

@@ -0,0 +1,262 @@
+<!--
+  * 部门树形结构
+  *
+  * @Author:    DCCloud
+  * @Date:      2022-08-08 20:46:18
+-->
+<template>
+  <a-card class="tree-container">
+    <a-row class="smart-margin-bottom10">
+      <a-input v-model:value.trim="keywords" placeholder="请输入部门名称" />
+    </a-row>
+    <a-tree
+      v-if="!_.isEmpty(departmentTreeData)"
+      v-model:selectedKeys="selectedKeys"
+      v-model:checkedKeys="checkedKeys"
+      :treeData="departmentTreeData"
+      :fieldNames="{ title: 'name', key: 'departmentId', value: 'departmentId' }"
+      :checkable="props.checkable"
+      :checkStrictly="props.checkStrictly"
+      :selectable="!props.checkable"
+      :defaultExpandAll="true"
+      @select="treeSelectChange"
+    >
+      <template #title="item">
+        {{ item.name }}
+        <a-dropdown>
+          <MoreOutlined />
+          <template #overlay>
+            <a-menu>
+              <a-menu-item>
+                <a href="javascript:;">新建目录</a>
+              </a-menu-item>
+              <a-menu-item>
+                <a href="javascript:;">编辑</a>
+              </a-menu-item>
+              <a-menu-item>
+                <a href="javascript:;">显示与查阅权限</a>
+              </a-menu-item>
+              <a-menu-item>
+                <a href="javascript:;">删除</a>
+              </a-menu-item>
+            </a-menu>
+          </template>
+        </a-dropdown>
+      </template>
+    </a-tree>
+    <div class="no-data" v-else>暂无结果</div>
+  </a-card>
+</template>
+<script setup>
+  import { onMounted, onUnmounted, ref, watch } from 'vue';
+  import _ from 'lodash';
+  import { departmentApi } from '/src/api/system/department-api';
+  import departmentEmitter from '../../department-mitt';
+  import { smartSentry } from '/src/lib/smart-sentry';
+
+  const DEPARTMENT_PARENT_ID = 0;
+
+  // ----------------------- 组件参数 ---------------------
+
+  const props = defineProps({
+    // 是否可以选中
+    checkable: {
+      type: Boolean,
+      default: false,
+    },
+    // 父子节点选中状态不再关联
+    checkStrictly: {
+      type: Boolean,
+      default: false,
+    },
+    // 树高度 超出出滚动条
+    height: Number,
+    // 显示菜单
+    showMenu: {
+      type: Boolean,
+      default: false,
+    },
+  });
+
+  // ----------------------- 部门树的展示 ---------------------
+  const topDepartmentId = ref();
+  // 所有部门列表
+  const departmentList = ref([]);
+  // 部门树形数据
+  const departmentTreeData = ref([]);
+  // 存放部门id和部门,用于查找
+  const idInfoMap = ref(new Map());
+
+  onMounted(() => {
+    queryDepartmentTree();
+  });
+
+  // 刷新
+  async function refresh() {
+    await queryDepartmentTree();
+    if (currentSelectedDepartmentId.value) {
+      selectTree(currentSelectedDepartmentId.value);
+    }
+  }
+
+  // 查询部门列表并构建 部门树
+  async function queryDepartmentTree() {
+    let res = await departmentApi.queryAllDepartment();
+    let data = res.data;
+    departmentList.value = data;
+    departmentTreeData.value = buildDepartmentTree(data, DEPARTMENT_PARENT_ID);
+
+    data.forEach((e) => {
+      idInfoMap.value.set(e.departmentId, e);
+    });
+
+    // 默认显示 最顶级ID为列表中返回的第一条数据的ID
+    if (!_.isEmpty(departmentTreeData.value) && departmentTreeData.value.length > 0) {
+      topDepartmentId.value = departmentTreeData.value[0].departmentId;
+    }
+
+    selectTree(departmentTreeData.value[0].departmentId);
+  }
+
+  // 构建部门树
+  function buildDepartmentTree(data, parentId) {
+    let children = data.filter((e) => e.parentId === parentId) || [];
+    children.forEach((e) => {
+      e.children = buildDepartmentTree(data, e.departmentId);
+    });
+    updateDepartmentPreIdAndNextId(children);
+    return children;
+  }
+
+  // 更新树的前置id和后置id
+  function updateDepartmentPreIdAndNextId(data) {
+    for (let index = 0; index < data.length; index++) {
+      if (index === 0) {
+        data[index].nextId = data.length > 1 ? data[1].departmentId : undefined;
+        continue;
+      }
+
+      if (index === data.length - 1) {
+        data[index].preId = data[index - 1].departmentId;
+        data[index].nextId = undefined;
+        continue;
+      }
+
+      data[index].preId = data[index - 1].departmentId;
+      data[index].nextId = data[index + 1].departmentId;
+    }
+  }
+
+  // ----------------------- 树的选中 ---------------------
+  const selectedKeys = ref([]);
+  const checkedKeys = ref([]);
+  const breadcrumb = ref([]);
+  const currentSelectedDepartmentId = ref();
+  const selectedDepartmentChildren = ref([]);
+
+  departmentEmitter.on('selectTree', selectTree);
+
+  function selectTree(id) {
+    selectedKeys.value = [id];
+    treeSelectChange(selectedKeys.value);
+  }
+
+  function treeSelectChange(idList) {
+    if (_.isEmpty(idList)) {
+      breadcrumb.value = [];
+      selectedDepartmentChildren.value = [];
+      return;
+    }
+    let id = idList[0];
+    selectedDepartmentChildren.value = departmentList.value.filter((e) => e.parentId == id);
+    let filterDepartmentList = [];
+    recursionFilterDepartment(filterDepartmentList, id, true);
+    breadcrumb.value = filterDepartmentList.map((e) => e.name);
+  }
+
+  // -----------------------  筛选 ---------------------
+  const keywords = ref('');
+  watch(
+    () => keywords.value,
+    () => {
+      onSearch();
+    }
+  );
+
+  // 筛选
+  function onSearch() {
+    if (!keywords.value) {
+      departmentTreeData.value = buildDepartmentTree(departmentList.value, DEPARTMENT_PARENT_ID);
+      return;
+    }
+    let originData = departmentList.value.concat();
+    if (!originData) {
+      return;
+    }
+    // 筛选出名称符合的部门
+    let filterDepartment = originData.filter((e) => e.name.indexOf(keywords.value) > -1);
+    let filterDepartmentList = [];
+    // 循环筛选出的部门 构建部门树
+    filterDepartment.forEach((e) => {
+      recursionFilterDepartment(filterDepartmentList, e.departmentId, false);
+    });
+
+    departmentTreeData.value = buildDepartmentTree(filterDepartmentList, DEPARTMENT_PARENT_ID);
+  }
+
+  // 根据ID递归筛选部门
+  function recursionFilterDepartment(resList, id, unshift) {
+    let info = idInfoMap.value.get(id);
+    if (!info || resList.some((e) => e.departmentId == id)) {
+      return;
+    }
+    if (unshift) {
+      resList.unshift(info);
+    } else {
+      resList.push(info);
+    }
+    if (info.parentId && info.parentId != 0) {
+      recursionFilterDepartment(resList, info.parentId, unshift);
+    }
+  }
+
+  onUnmounted(() => {
+    departmentEmitter.all.clear();
+  });
+
+  // ----------------------- 以下是暴露的方法内容 ----------------------------
+  defineExpose({
+    queryDepartmentTree,
+    selectedDepartmentChildren,
+    breadcrumb,
+    selectedKeys,
+    checkedKeys,
+    keywords,
+  });
+</script>
+<style scoped lang="less">
+  ::v-deep .ant-tree-treenode {
+    width: 100%;
+  }
+  ::v-deep .ant-tree-node-content-wrapper {
+    width: 100%;
+  }
+  ::v-deep .ant-tree-title {
+    display: flex;
+    justify-content: space-between;
+  }
+
+  .tree-container {
+    width: 100%;
+    height: 100%;
+
+    .tree {
+      height: 618px;
+      margin-top: 10px;
+      overflow-x: hidden;
+    }
+    .no-data {
+      margin: 10px;
+    }
+  }
+</style>

+ 170 - 0
src/views/support-manage/Archive/project-archive/archive-detail/index.vue

@@ -0,0 +1,170 @@
+<template>
+  <div class="page-detail">
+    <page-detail-layout :tabs="tabs" v-model:tab-active-key="tabActiveKey" :index-config="indexConfig" :title="标题内容">
+      <template #titleRight>
+        <img v-if="customerDetailData?.customerGrade?.[0].valueCode === 'S'" src="/@/assets/images/page-detail-layout/customer/SS_user.png" alt="" />
+        <img v-if="customerDetailData?.customerGrade?.[0].valueCode === 'A'" src="/@/assets/images/page-detail-layout/customer/AA_user.png" alt="" />
+        <img v-if="customerDetailData?.customerGrade?.[0].valueCode === 'B'" src="/@/assets/images/page-detail-layout/customer/BB_user.png" alt="" />
+        <img v-if="customerDetailData?.customerGrade?.[0].valueCode === 'C'" src="/@/assets/images/page-detail-layout/customer/CC_user.png" alt="" />
+        <bs-dic-tag :dicts="customerDetailData?.customerSource" />
+      </template>
+
+      <template #toolBtn> </template>
+
+      <template #titleBottom>
+        <a-tag color="#f0f4fe" v-for="(tagItem, tagIndex) in tagList" :key="tagIndex" @click="tagItem?.click(tagItem)" style="cursor: pointer">
+          <div class="tag-stl">
+            <img :src="tagItem.icon" alt="" />
+            <span class="title-render">{{ tagItem.title }}:{{ tagItem.value }}</span>
+          </div>
+        </a-tag>
+      </template>
+
+      <template #BasicInfo>
+        <BasicInfo :id="route.query.id" />
+      </template>
+      <template #ArchiveTree>
+        <ArchiveTree :id="route.query.id" />
+      </template>
+    </page-detail-layout>
+  </div>
+</template>
+
+<script setup>
+  import { onMounted, reactive, ref, watch } from 'vue';
+  import { useRoute } from 'vue-router';
+  import PageDetailLayout from '/@/components/business/page-detail-layout/index.vue';
+  import BasicInfo from '/@/views/support-manage/competition/opponent/opponent-detail/components/BasicInfo/index.vue';
+  import ArchiveTree from '/@/views/support-manage/Archive/project-archive/archive-detail/components/ArchiveTree/index.vue';
+
+  import { fetchCustomerHeaderInfo, fetchCustomerDetail } from '/@/api/customer-manage/index.js';
+
+  const route = useRoute();
+  const headerIndexData = ref(null);
+
+  const getImgUrl = (name) => {
+    return new URL('/src/assets/images/page-detail-layout/customer/' + name + '.svg', import.meta.url).href;
+  };
+
+  const tagList = ref([
+    {
+      title: '客户类型',
+      icon: getImgUrl('icon-tianyancha'),
+    },
+    {
+      title: '客户编码',
+      icon: getImgUrl('icon-xiansuodengji'),
+    },
+    {
+      title: '所在省市',
+      icon: getImgUrl('icon-biaoqianguanli'),
+    },
+  ]);
+
+  const tabs = ref([
+    {
+      title: '基本信息',
+      key: 'BasicInfo',
+      slotName: 'BasicInfo',
+      selectedIcon: getImgUrl('icon-jibenxinxi-all'),
+      unSelectedIcon: getImgUrl('icon-jibenxinxi'),
+    },
+     {
+      title: '项目档案',
+      key: 'ArchiveTree',
+      slotName: 'ArchiveTree',
+      selectedIcon: getImgUrl('icon-jibenxinxi-all'),
+      unSelectedIcon: getImgUrl('icon-jibenxinxi'),
+    },
+  ]);
+
+  const customerDetailData = ref(null);
+
+  const indexConfig = ref({
+    sourceData: [],
+    labelKey: 'label',
+    valueKey: 'value',
+  });
+
+  const setSourceData = (resData) => {
+    indexConfig.value = {
+      sourceData: [
+        {
+          label: '属性',
+          value: resData.contractQuantity || 0,
+        },
+        {
+          label: '注册资本',
+          value: resData.contractAmount || 0,
+        },
+        {
+          label: '注册日期',
+          value: resData.paymentAmount || 0,
+        },
+        {
+          label: '员工人数',
+          value: resData.invoiceAmount || 0,
+        },
+        {
+          label: '添加人',
+          value: resData.unpaidAmount || 0,
+        },
+        {
+          label: '添加时间',
+          value: resData.unpaidAmount || 0,
+        },
+      ],
+      labelKey: 'label',
+      valueKey: 'value',
+    };
+  };
+
+  onMounted(() => {
+    fetchCustomerHeaderInfo(route.query.id).then((res) => {
+      headerIndexData.value = res.data;
+      setSourceData(headerIndexData.value);
+    });
+
+    fetchCustomerDetail(route.query.id).then((res) => {
+      customerDetailData.value = res.data;
+    });
+  });
+
+  watch(headerIndexData, (newVal) => {
+    if (newVal) {
+      tagList.value = [
+        {
+          title: '客户类型',
+          icon: getImgUrl('icon-tianyancha'),
+          value: newVal.contractQuantity,
+        },
+        {
+          title: '客户编码',
+          icon: getImgUrl('icon-xiansuodengji'),
+          value: newVal.contractQuantity,
+        },
+        {
+          title: '所在省市',
+          icon: getImgUrl('icon-biaoqianguanli'),
+          value: newVal.contractQuantity,
+        },
+      ];
+    }
+  });
+</script>
+
+<style lang="scss" scoped>
+  .page-detail {
+    width: 100%;
+
+    .tag-stl {
+      display: flex;
+      gap: 5px;
+      align-items: center;
+      .title-render {
+        color: #999999;
+        font-size: 14px;
+      }
+    }
+  }
+</style>

+ 235 - 0
src/views/support-manage/Archive/project-archive/index.vue

@@ -0,0 +1,235 @@
+<template>
+  <div class="table-demo">
+    <bs-table v-bind="tableOptions">
+      <template #searchRight>
+        <div>
+          <a-button type="primary" @click="handleOpponentRegistration">
+            <span>竞争对手登记</span>
+          </a-button>
+        </div>
+      </template>
+      <template #slotVue_default="{}">
+        <a-dropdown>
+          <a class="ant-dropdown-link" @click.prevent> 12项 </a>
+          <template #overlay>
+            <a-menu>
+              <a-menu-item>
+                <a-table :dataSource="dataSource" :columns="columns" :pagination="false"/>
+              </a-menu-item>
+            </a-menu>
+          </template>
+        </a-dropdown>
+      </template>
+    </bs-table>
+  </div>
+</template>
+
+<script setup lang="jsx">
+  import BsTable, { useBsTable } from '/@/components/BsUi/Table/index.js';
+  import { onMounted, ref } from 'vue';
+  import { useRouter } from 'vue-router';
+  import { DISPLAY_STATE } from '/@/components/BsUi/constant.js';
+
+  const router = useRouter();
+  const dataSource = ref([
+    {
+      key: '1',
+      name: '胡彦斌',
+      age: 32,
+      address: '西湖区湖底公园1号',
+    },
+    {
+      key: '2',
+      name: '胡彦祖',
+      age: 42,
+      address: '西湖区湖底公园1号',
+    },
+  ]);
+  const columns = ref([
+    {
+      title: '姓名',
+      dataIndex: 'name',
+      key: 'name',
+      align: 'center',
+    },
+    {
+      title: '年龄',
+      dataIndex: 'age',
+      key: 'age',
+      align: 'center',
+    },
+    {
+      title: '住址',
+      dataIndex: 'address',
+      key: 'address',
+      align: 'center',
+    },
+  ]);
+
+  onMounted(() => {
+    refreshTable();
+  });
+
+  const { tableOptions, setTablePropsValue, getTablePropsValue, refreshTable } = useBsTable({
+    tableOptions: {
+      url: '/supports/project/queryPage',
+      gridOptions: {
+        loading: false,
+        columns: [
+          {
+            field: '',
+            title: '竞争对手名称',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '竞争对手ID',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '曾用名',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '注册地址',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '单位类型',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '注册资本(元)',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '注册日期',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '员工人数',
+            width: 150,
+          },
+          {
+            field: 'slotVue',
+            title: '累计资质管理',
+            align: 'center',
+            width: 150,
+            slots: {
+              default: 'slotVue_default',
+            },
+          },
+          {
+            field: '',
+            title: '已登记参标数量',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '已登记中标数量',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '添加人',
+            width: 150,
+          },
+          {
+            field: '',
+            title: '添加时间',
+            width: 150,
+          },
+          {
+            field: 'opt',
+            title: '操作',
+            width: '120px',
+            fixed: 'right',
+            align: 'center',
+          },
+          {
+            cellRender: {
+              name: 'CellOption',
+              extraProps: {
+                buttons: [
+                  {
+                    title: '查看详情',
+                    code: 'view',
+                    display: ({ row }) => {
+                      return DISPLAY_STATE.VISIBLE;
+                    },
+                    disabled({ row }) {
+                      return false;
+                    },
+                    onClick({ row }) {
+                      goDetailPage(row);
+                    },
+                    extraProps: {},
+                  },
+                ],
+              },
+            },
+          },
+        ],
+      },
+      searchConfig: {
+        enabled: true,
+        fieldSpan: 4,
+        fields: [
+          {
+            field: '',
+            component: 'a-input',
+            componentProps: {
+              placeholder: '请输入竞争对手名称',
+            },
+          },
+          {
+            field: '',
+            component: 'a-select',
+            componentProps: {
+              placeholder: '请选择单位类型',
+            },
+          },
+          {
+            field: '',
+            component: 'a-select',
+            componentProps: {
+              placeholder: '请选择资质',
+            },
+          },
+        ],
+      },
+      pagerConfig: {
+        isFixed: true,
+        enabled: true,
+        pageSize: 10,
+        pageNum: 1,
+        total: 0,
+      },
+    },
+  });
+
+  const goDetailPage = (record) => {
+    console.log(record.id);
+    router.push({
+      path: '/support-manage/Archive/project-archive/archive-detail',
+      query: {
+        id: record.id,
+      },
+    });
+  };
+
+  const handleOpponentRegistration = () => {
+    router.push('/support-manage/competition/opponent/create-opponent');
+  };
+</script>
+
+<style scoped lang="scss">
+  .table-demo {
+  }
+</style>

+ 9 - 6
src/views/support-manage/bidding/performance/performance-detail/index.vue

@@ -16,15 +16,19 @@
         </a-button>
         <a-button ghost type="primary" size="small" @click="customerTransferModalRef.showModal()">
           <RightSquareOutlined />
-          <span> 放弃 </span></a-button
-        >
+          <span> 转入 </span>
+        </a-button>
+        <a-button ghost type="primary" size="small" @click="customerTransferModalRef.showModal()">
+          <RightSquareOutlined />
+          <span> 放弃 </span>
+        </a-button>
       </template>
 
       <template #titleBottom>
         <a-tag color="#f0f4fe" v-for="(tagItem, tagIndex) in tagList" :key="tagIndex" @click="tagItem?.click(tagItem)" style="cursor: pointer">
           <div class="tag-stl">
             <img :src="tagItem.icon" alt="" />
-             <span class="title-render">{{ tagItem.title }}:{{ tagItem.value }}</span>
+            <span class="title-render">{{ tagItem.title }}:{{ tagItem.value }}</span>
           </div>
         </a-tag>
       </template>
@@ -41,7 +45,6 @@
         <EditReport :id="route.query.id" />
       </template>
     </page-detail-layout>
-
   </div>
 </template>
 
@@ -49,7 +52,7 @@
   import { onMounted, reactive, ref, watch } from 'vue';
   import { useRoute } from 'vue-router';
   import PageDetailLayout from '/@/components/business/page-detail-layout/index.vue';
-  import BasicInfo from '/@/views/customer-manage/customer-detail/components/BasicInfo/index.vue';
+  import BasicInfo from '/@/views/support-manage/bidding/performance/performance-detail/components/BasicInfo/index.vue';
   import InfoMaterial from '/@/views/customer-manage/customer-detail/components/InfoMaterial/index.vue';
   import EditReport from '/@/views/customer-manage/customer-detail/components/EditReport/index.vue';
 
@@ -70,7 +73,7 @@
     return new URL('/src/assets/images/page-detail-layout/customer/' + name + '.svg', import.meta.url).href;
   };
 
-   const tagList = ref([
+  const tagList = ref([
     {
       title: '客户类型',
       icon: getImgUrl('icon-tianyancha'),

+ 0 - 1
src/views/support-manage/competition/opponent/create-opponent/components/TableInfoSelect.vue

@@ -10,7 +10,6 @@
 <script setup lang="jsx">
   import BsModalTableSelector from '/@/components/BsUi/ModalTableSelector/index.vue';
   import { ref } from 'vue';
-  import { useBsTable } from '/@/components/BsUi/Table/index.js';
   import { useBsModal } from '/@/components/BsUi/Modal/index.js';
 
   const emit = defineEmits(['selectedRowList']);

+ 67 - 65
src/views/support-manage/competition/opponent/create-opponent/index.vue

@@ -17,7 +17,7 @@
               <a-col :span="16">
                 <a-form-item label="竞争对手名称" name="regionType" class="smart-query-form-item">
                   <a-input v-model:value="formModel.customerName" placeholder="请输入竞争对手名称" @click="showSelectProj" />
-                  <table-info-select ref="customerSelectRef" @selectedRowList="handleSelect" :bs-table-bean="bsTableBean" />
+                  <!-- <table-info-select ref="customerSelectRef" @selectedRowList="handleSelect" :bs-table-bean="bsTableBean" /> -->
                 </a-form-item>
               </a-col>
               <a-col :span="8">
@@ -307,70 +307,72 @@
   const customerSelectRef = ref(null);
 
   //表格选择器配置项
-  const bsTableBean = useBsTable({
-    tableOptions: {
-      isLoadRequest: false,
-      url: '/supports/customer/queryPage',
-      gridOptions: {
-        loading: false,
-        columns: [
-          {
-            field: 'id',
-            title: 'ID',
-          },
-          {
-            field: 'customerName',
-            title: '甲方名称',
-          },
-          {
-            field: 'customerType',
-            title: '甲方类型',
-            cellRender: {
-              name: 'CellDict',
-            },
-          },
-          {
-            field: 'provinceCityDistrict',
-            title: '省市区',
-          },
-        ],
-      },
-      searchConfig: {
-        enabled: false,
-        fieldSpan: 4,
-        fields: [
-          {
-            field: 'customerName',
-            label: '',
-            component: 'a-input',
-            componentProps: {
-              placeholder: '请输入客户名称',
-            },
-          },
-        ],
-      },
-      pagerConfig: {
-        enable: true,
-        pageSize: 10,
-        pageNum: 1,
-      },
-      toolbarConfig: {
-        enable: false,
-      },
-      // 每次查询接口之前,都会调用这个回调函数
-      tableSearchBeforeBiz() {
-        console.log('表格搜索前');
-      },
-      // 表格初始化之前,只加载一次
-      beforeMount() {
-        console.log('表格加载前');
-      },
-      // 表格初始化完成,只加载一次
-      mounted(gridRef) {
-        console.log('表格加载后', gridRef);
-      },
-    },
-  });
+  // const bsTableBean = useBsTable({
+  //   tableOptions: {
+  //     isLoadRequest: false,
+  //     url: '/supports/customer/queryPage',
+  //     gridOptions: {
+  //       loading: false,
+  //       columns: [
+  //         {
+  //           field: 'id',
+  //           title: 'ID',
+  //         },
+  //         {
+  //           field: 'customerName',
+  //           title: '甲方名称',
+  //         },
+  //         {
+  //           field: 'customerType',
+  //           title: '甲方类型',
+  //           cellRender: {
+  //             name: 'CellDict',
+  //           },
+  //         },
+  //         {
+  //           field: 'provinceCityDistrict',
+  //           title: '省市区',
+  //         },
+  //       ],
+        
+        
+  //     },
+  //     searchConfig: {
+  //       enabled: false,
+  //       fieldSpan: 4,
+  //       fields: [
+  //         {
+  //           field: 'customerName',
+  //           label: '',
+  //           component: 'a-input',
+  //           componentProps: {
+  //             placeholder: '请输入客户名称',
+  //           },
+  //         },
+  //       ],
+  //     },
+  //     pagerConfig: {
+  //       enable: true,
+  //       pageSize: 10,
+  //       pageNum: 1,
+  //     },
+  //     toolbarConfig: {
+  //       enable: false,
+  //     },
+  //     // 每次查询接口之前,都会调用这个回调函数
+  //     tableSearchBeforeBiz() {
+  //       console.log('表格搜索前');
+  //     },
+  //     // 表格初始化之前,只加载一次
+  //     beforeMount() {
+  //       console.log('表格加载前');
+  //     },
+  //     // 表格初始化完成,只加载一次
+  //     mounted(gridRef) {
+  //       console.log('表格加载后', gridRef);
+  //     },
+  //   },
+  // });
 
   //表格选择器开窗
   function showSelectProj() {

+ 22 - 99
src/views/support-manage/competition/opponent/index.vue

@@ -1,26 +1,6 @@
 <template>
   <div class="table-demo">
-    <bs-table v-bind="tableOptions">
-      <template #searchRight>
-        <div>
-          <a-button type="primary" @click="handleOpponentRegistration">
-            <span>竞争对手登记</span>
-          </a-button>
-        </div>
-      </template>
-      <template #slotVue_default="{}">
-        <a-dropdown>
-          <a class="ant-dropdown-link" @click.prevent> 12项 </a>
-          <template #overlay>
-            <a-menu>
-              <a-menu-item>
-                <a-table :dataSource="dataSource" :columns="columns" :pagination="false"/>
-              </a-menu-item>
-            </a-menu>
-          </template>
-        </a-dropdown>
-      </template>
-    </bs-table>
+    <bs-table v-bind="tableOptions"> </bs-table>
   </div>
 </template>
 
@@ -31,41 +11,6 @@
   import { DISPLAY_STATE } from '/@/components/BsUi/constant.js';
 
   const router = useRouter();
-  const dataSource = ref([
-    {
-      key: '1',
-      name: '胡彦斌',
-      age: 32,
-      address: '西湖区湖底公园1号',
-    },
-    {
-      key: '2',
-      name: '胡彦祖',
-      age: 42,
-      address: '西湖区湖底公园1号',
-    },
-  ]);
-  const columns = ref([
-    {
-      title: '姓名',
-      dataIndex: 'name',
-      key: 'name',
-      align: 'center',
-    },
-    {
-      title: '年龄',
-      dataIndex: 'age',
-      key: 'age',
-      align: 'center',
-    },
-    {
-      title: '住址',
-      dataIndex: 'address',
-      key: 'address',
-      align: 'center',
-    },
-  ]);
-
   onMounted(() => {
     refreshTable();
   });
@@ -78,72 +23,48 @@
         columns: [
           {
             field: '',
-            title: '竞争对手名称',
-            width: 150,
+            title: '项目名称',
           },
           {
             field: '',
-            title: '竞争对手ID',
-            width: 150,
+            title: '项目地址',
           },
           {
             field: '',
-            title: '曾用名',
-            width: 150,
+            title: '预计合同金额(元)',
           },
           {
             field: '',
-            title: '注册地址',
-            width: 150,
+            title: '项目来源',
           },
           {
             field: '',
-            title: '单位类型',
-            width: 150,
+            title: '投标类型',
           },
           {
             field: '',
-            title: '注册资本(元)',
-            width: 150,
+            title: '产品类型',
           },
           {
             field: '',
-            title: '注册日期',
-            width: 150,
+            title: '预计开标日期',
           },
           {
             field: '',
-            title: '员工人数',
-            width: 150,
+            title: '预计投标',
           },
           {
             field: 'slotVue',
-            title: '累计资质管理',
+            title: '归属营销',
             align: 'center',
-            width: 150,
-            slots: {
-              default: 'slotVue_default',
-            },
           },
           {
             field: '',
-            title: '已登记参标数量',
-            width: 150,
+            title: '操作人',
           },
           {
             field: '',
-            title: '已登记中标数量',
-            width: 150,
-          },
-          {
-            field: '',
-            title: '添加人',
-            width: 150,
-          },
-          {
-            field: '',
-            title: '添加时间',
-            width: 150,
+            title: '操作日期',
           },
           {
             field: 'opt',
@@ -185,27 +106,33 @@
             field: '',
             component: 'a-input',
             componentProps: {
-              placeholder: '请输入竞争对手名称',
+              placeholder: '请输入项目名称',
+            },
+          },
+          {
+            field: '',
+            component: 'a-select',
+            componentProps: {
+              placeholder: '请选择项目ID',
             },
           },
           {
             field: '',
             component: 'a-select',
             componentProps: {
-              placeholder: '请选择单位类型',
+              placeholder: '请选择地址',
             },
           },
           {
             field: '',
             component: 'a-select',
             componentProps: {
-              placeholder: '请选择资质',
+              placeholder: '请选择项目状态',
             },
           },
         ],
       },
       pagerConfig: {
-        isFixed: true,
         enabled: true,
         pageSize: 10,
         pageNum: 1,
@@ -223,10 +150,6 @@
       },
     });
   };
-
-  const handleOpponentRegistration = () => {
-    router.push('/support-manage/competition/opponent/create-opponent');
-  };
 </script>
 
 <style scoped lang="scss">

+ 5 - 38
src/views/support-manage/competition/opponent/opponent-detail/components/ProjectInfo/index.vue

@@ -1,9 +1,9 @@
 <template>
   <div class="table-demo">
     <bs-table v-bind="tableOptions">
-       <template #toolbarTop>
+      <template #toolbarTop>
         <a-space>
-         <a-button type="primary" @click="goHistroyProjectPage">
+          <a-button type="primary" @click="goHistroyProjectPage">
             <template #icon>
               <PlusOutlined />
             </template>
@@ -24,14 +24,12 @@
 
 <script setup lang="jsx">
   import BsTable, { useBsTable } from '/@/components/BsUi/Table/index.js';
-  import { onMounted, h,ref, watch } from 'vue';
+  import { onMounted, h, ref, watch } from 'vue';
   import { useRouter } from 'vue-router';
-  import { DISPLAY_STATE } from '/@/components/BsUi/constant.js';
 
   import HistoryProjDetail from '/@/views/support-manage/competition/opponent/opponent-detail/components/ProjectInfo/modules/HistoryProjDetail.vue';
   import ProjectQuotation from '/@/views/support-manage/competition/opponent/opponent-detail/components/ProjectInfo/modules/ProjectQuotation.vue';
 
-  const selectedStatus = ref(''); // 定义状态变量
   const HistoryProjDetailRef = ref();
   const ProjectQuotationRef = ref();
 
@@ -51,7 +49,6 @@
             width: 100,
             align: 'center',
           },
-
           {
             title: '项目名称',
             field: 'clueName',
@@ -61,7 +58,6 @@
             title: '项目报价',
             // field: 'projectType',
             align: 'center',
-
             slots: {
               default({ row, column }) {
                 return (
@@ -98,7 +94,6 @@
             title: '项目类型',
             // field: 'tendersType',
             align: 'center',
-
             slots: {
               default({ row, column }) {
                 return <span>{row?.projectType?.[0]?.valueName || ''}</span>;
@@ -109,7 +104,6 @@
             title: '产品类型',
             // field: 'tendersType',
             align: 'center',
-
             slots: {
               default({ row, column }) {
                 return <span>{row?.engineeringAttribute?.[0]?.valueName || ''}</span>;
@@ -132,33 +126,17 @@
             align: 'center',
           },
         ],
-        data: [
-          {
-            id: 1,
-            name: '测试数据',
-            dictField: [
-              {
-                dictKeyId: '',
-                dictValueId: '',
-                remark: '',
-                sort: 3,
-                status: 1,
-                valueCode: '03',
-                valueName: '微信公众号',
-              },
-            ],
-          },
-        ], // 模拟数据源
       },
       pagerConfig: {
         enabled: true,
+        isFixed: true,
         pageSize: 10,
         pageNum: 1,
       },
       toolbarConfig: {},
       tableSearchBeforeBiz() {
         const searchParams = getValue('searchConfig.data');
-        setValue('searchConfig.data', { ...searchParams, status: selectedStatus.value });
+        setValue('searchConfig.data', { ...searchParams });
       },
     },
   });
@@ -178,17 +156,6 @@
   function goProjectQuotation() {
     ProjectQuotationRef.value.showModal();
   }
-
-  //查看项目详情
-  function goDetailPage(record) {
-    console.log('record', record);
-    router.push({
-      path: '/market-manage/external-manage/project-manage/single-project/',
-      query: {
-        id: record.id,
-      },
-    });
-  }
 </script>
 
 <style scoped lang="scss">