zhangwei
2025-08-08 d71422ecb4e6a0c855e94e0416e4fc52387dec18
'关注项目'
3个文件已修改
5个文件已添加
1569 ■■■■■ 已修改文件
src/router/modules/item.ts 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/aboutItem/form.vue 410 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/aboutItem/index.vue 334 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/aboutItem/utils/hook.tsx 489 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/aboutItem/utils/rule.ts 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/aboutItem/utils/types.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dept/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/dept/utils/hook.tsx 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/modules/item.ts
@@ -1,21 +1,44 @@
export default {
  path: "/item",
  meta: {
    title: "项目管理",
    icon: "mdi:chart-timeline"
  },
  children: [
    {
      // path随便写,但前面必须有个 `/`
      path: "/item",
      // component对应的值前不需要加 / 值对应的是实际业务 `.vue` 或 `.tsx` 代码路径
      component: () => import("@/views/system/dept/index.vue"),
      name: "item",
      meta: {
        title: "项目管理",
        roles: ["DLJG", "CGR"]
        // showLink:false
export default [
  {
    path: "/item",
    meta: {
      title: "项目管理",
      icon: "mdi:chart-timeline"
    },
    children: [
      {
        // path随便写,但前面必须有个 `/`
        path: "/item",
        // component对应的值前不需要加 / 值对应的是实际业务 `.vue` 或 `.tsx` 代码路径
        component: () => import("@/views/system/dept/index.vue"),
        name: "item",
        meta: {
          title: "项目管理",
          roles: ["DLJG", "CGR"]
          // showLink:false
        }
      }
    }
  ]
} satisfies RouteConfigsTable;
    ]
  },
  {
    path: "/aboutItem",
    meta: {
      title: "关注项目",
      icon: "pajamas:work-item-new"
    },
    children: [
      {
        // path随便写,但前面必须有个 `/`
        path: "/aboutItem",
        // component对应的值前不需要加 / 值对应的是实际业务 `.vue` 或 `.tsx` 代码路径
        component: () => import("@/views/system/aboutItem/index.vue"),
        name: "aboutItem",
        meta: {
          title: "关注项目",
          roles: ["DLJG", "GYS"]
          // showLink:false
        }
      }
    ]
  }
] satisfies Array<RouteConfigsTable>;
src/views/system/aboutItem/form.vue
New file
@@ -0,0 +1,410 @@
<script setup lang="ts">
import { onMounted, ref, reactive } from "vue";
import ReCol from "@/components/ReCol";
import { formRules } from "./utils/rule";
import { FormProps } from "./utils/types";
import { usePublicHooks } from "../hooks";
import { useDept } from "./utils/hook";
import { Operation } from "@element-plus/icons-vue";
import { getCaigoufangshiList } from "@/api/item/index";
const { state } = useDept();
const props = withDefaults(defineProps<FormProps>(), {
  formInline: () => ({
    id: "",
    projectCode: "", // 项目编号(必填)
    projectName: "", // 项目名称(必填)
    hangyepinmu: null, // 行业品目(可选)
    caigoufangshi: null, // 采购方式(可选)
    caigouyusuan: null, // 采购预算(可选)
    dingbiaoguize: null, // 定标规则(可选)
    baomingfei: null, // 报名费(可选)
    toubiaobaozhengjin: null, // 投标保证金(可选)
    lianhetitoubiao: null, // 联合体投标(可选)
    kaibiaofangshi: null, // 开标方式(可选)
    shifoufenbao: "false", // 是否分包(可选)
    shifoutuisongxuanchuan: "true", // 是否推送宣传(可选)
    caigourenmingcheng: null, // 采购人名称(可选)
    xingzhengquyu: [], // 行政区域(可选)
    xingzhengquyuName: null, // 行政区域名称(可选)
    jigoudaima: null, // 机构代码(可选)
    daimaleixing: null, // 代码类型(可选)
    lianxiren: null, // 联系人(可选)
    lianxidianhua: null, // 联系电话(可选)
    tongxindizhi: null, // 通信地址(可选)
    dianziyoujian: null, // 电子邮件(可选)
    xiangmujingbanren: null, // 项目经办人(可选)
    zhiwu: null, // 职务(可选)
    jingbanrendianhua: null, // 经办人电话(可选)
    dailijigoumingcheng: null, // 代理机构名称(可选)
    dailiLianxiren: null, // 代理机构联系人(可选)
    dailiLianxidianhua: null, // 代理机构联系电话(可选)
    dailiDianziyoujian: null, // 代理机构电子邮件(可选)
    dailiTongxindizhi: null, // 代理机构通信地址(可选)
    dailiXiangmujingli: null, // 代理机构项目经理(可选
    dailijingliLianxidianhua: null // 代理机构项目经理联系电话(可选)
  })
});
const ruleFormRef = ref();
const { switchStyle } = usePublicHooks();
const newFormInline = ref(props.formInline);
function getRef() {
  return ruleFormRef.value;
}
const handleChange = value => {
  console.log(value);
};
defineExpose({ getRef });
onMounted(async () => {});
</script>
<template>
  <el-form
    ref="ruleFormRef"
    :model="newFormInline"
    :rules="formRules"
    label-width="110px"
  >
    <el-row :gutter="30">
      <re-col>
        <p class="flex items-center">
          <el-icon color="#409EFF" class="m-2" size="large">
            <Operation />
          </el-icon>
          <el-text class="mx-1" size="large" type="primary" tag="b">
            项目信息
          </el-text>
        </p>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="项目名称" prop="projectName">
          <el-input
            v-model="newFormInline.projectName"
            clearable
            placeholder="请输入项目名称"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="项目编号" prop="projectCode">
          <el-input
            v-model="newFormInline.projectCode"
            clearable
            placeholder="请输入项目编号"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="行业品目" prop="hangyepinmu">
          <el-select
            v-model="newFormInline.hangyepinmu"
            placeholder="请选择行业品目"
            clearable
            class="w-[100%]!"
          >
            <el-option
              v-for="item in state.hangyepingmuList"
              :key="item.id"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="采购方式" prop="caigoufangshi">
          <el-select
            v-model="newFormInline.caigoufangshi"
            placeholder="请选择采购方式"
            style="width: 240px"
          >
            <el-option
              v-for="item in state.caigoufangshiList"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="采购预算" prop="caigouyusuan">
          <el-input
            v-model="newFormInline.caigouyusuan"
            clearable
            placeholder="请输入采购预算"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="定制规划" prop="dingbiaoguize">
          <!-- <el-checkbox-group
            v-model="newFormInline.dingbiaoguize"
            placeholder="请选择状态"
            clearable
            class="w-[100%]!"
          >
            <el-checkbox label="最低价" value="最低价" />
            <el-checkbox label="综合评分" value="综合评分" />
          </el-checkbox-group> -->
          <el-radio-group v-model="newFormInline.dingbiaoguize">
            <el-radio value="最低价">最低价</el-radio>
            <el-radio value="综合评分">综合评分</el-radio>
          </el-radio-group>
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="报名费" prop="baomingfei">
          <el-input
            v-model="newFormInline.baomingfei"
            clearable
            placeholder="请输入报名费"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="投标保证金" prop="toubiaobaozhengjin">
          <el-input
            v-model="newFormInline.toubiaobaozhengjin"
            clearable
            placeholder="请输入投标保证金"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="联合体投标" prop="lianhetitoubiao">
          <el-radio-group v-model="newFormInline.lianhetitoubiao">
            <el-radio value="支持">支持</el-radio>
            <el-radio value="不支持">不支持</el-radio>
          </el-radio-group>
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="开标方式" prop="kaibiaofangshi">
          <el-radio-group v-model="newFormInline.kaibiaofangshi">
            <el-radio value="纸质标">纸质标</el-radio>
            <el-radio value="电子标">电子标</el-radio>
          </el-radio-group>
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="是否分包" prop="shifoufenbao">
          <el-radio-group v-model="newFormInline.shifoufenbao">
            <el-radio value="true">是</el-radio>
            <el-radio value="false">否</el-radio>
          </el-radio-group>
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="是否推送宣传" prop="shifoutuisongxuanchuan">
          <el-radio-group v-model="newFormInline.shifoutuisongxuanchuan">
            <el-radio value="true">是</el-radio>
            <el-radio value="false">否</el-radio>
          </el-radio-group>
        </el-form-item>
      </re-col>
      <re-col>
        <p class="flex items-center">
          <el-icon color="#409EFF" class="m-2" size="large">
            <Operation />
          </el-icon>
          <el-text class="mx-1" size="large" type="primary" tag="b">
            采购人信息
          </el-text>
        </p>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="采购人名称" prop="caigourenmingcheng">
          <el-input
            v-model="newFormInline.caigourenmingcheng"
            clearable
            placeholder="请输入采购人名称"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="行政区域" prop="xingzhengquyu">
          <el-cascader
            v-model="newFormInline.xingzhengquyu"
            class="w-full"
            :options="state.regionList"
            :props="{
              value: 'code',
              label: 'name',
              children: 'regions'
            }"
            clearable
            filterable
            placeholder="请选择区域"
            @change="handleChange"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="机构代码" prop="jigoudaima">
          <el-input
            v-model="newFormInline.jigoudaima"
            clearable
            placeholder="请输入机构代码"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="代码类型" prop="daimaleixing">
          <el-select
            v-model="newFormInline.daimaleixing"
            placeholder="请选择代码类型"
            style="width: 240px"
          >
            <el-option
              v-for="item in state.daimaleixingList"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="联系人" prop="lianxiren">
          <el-input
            v-model="newFormInline.lianxiren"
            clearable
            placeholder="请输入联系人"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="联系人电话" prop="lianxidianhua">
          <el-input
            v-model="newFormInline.lianxidianhua"
            clearable
            placeholder="请输入联系人电话"
          />
        </el-form-item>
      </re-col>
      <re-col :value="12" :xs="24" :sm="24">
        <el-form-item label="通信地址" prop="tongxindizhi">
          <el-input
            v-model="newFormInline.tongxindizhi"
            clearable
            placeholder="请输入通信地址"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="电子邮箱" prop="dianziyoujian">
          <el-input
            v-model="newFormInline.dianziyoujian"
            clearable
            placeholder="请输入电子邮箱"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="项目经办人" prop="xiangmujingbanren">
          <el-input
            v-model="newFormInline.xiangmujingbanren"
            clearable
            placeholder="请输入项目经办人"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="职务" prop="zhiwu">
          <el-input
            v-model="newFormInline.zhiwu"
            clearable
            placeholder="请输入职务"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="经办人电话" prop="jingbanrendianhua">
          <el-input
            v-model="newFormInline.jingbanrendianhua"
            clearable
            placeholder="请输入经办人电话"
          />
        </el-form-item>
      </re-col>
      <re-col>
        <p class="flex items-center">
          <el-icon color="#409EFF" class="m-2" size="large">
            <Operation />
          </el-icon>
          <el-text class="mx-1" size="large" type="primary" tag="b">
            代理机构信息
          </el-text>
        </p>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="代理机构名称" prop="dailijigoumingcheng">
          <el-input
            v-model="newFormInline.dailijigoumingcheng"
            clearable
            placeholder="请输入代理机构名称"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="联系人" prop="dailiLianxiren">
          <el-input
            v-model="newFormInline.dailiLianxiren"
            clearable
            placeholder="请输入联系人"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="联系电话" prop="dailiLianxidianhua">
          <el-input
            v-model="newFormInline.dailiLianxidianhua"
            clearable
            placeholder="请输入联系电话"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="电子邮箱" prop="dailiDianziyoujian">
          <el-input
            v-model="newFormInline.dailiDianziyoujian"
            clearable
            placeholder="请输入电子邮箱"
          />
        </el-form-item>
      </re-col>
      <re-col :value="12" :xs="24" :sm="24">
        <el-form-item label="通信地址" prop="dailiTongxindizhi">
          <el-input
            v-model="newFormInline.dailiTongxindizhi"
            clearable
            placeholder="请输入通信地址"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="项目经理" prop="dailiXiangmujingli">
          <el-input
            v-model="newFormInline.dailiXiangmujingli"
            clearable
            placeholder="请输入项目经理"
          />
        </el-form-item>
      </re-col>
      <re-col :value="6" :xs="24" :sm="24">
        <el-form-item label="联系电话" prop="dailijingliLianxidianhua">
          <el-input
            v-model="newFormInline.dailijingliLianxidianhua"
            clearable
            placeholder="请输入联系电话"
          />
        </el-form-item>
      </re-col>
    </el-row>
  </el-form>
</template>
src/views/system/aboutItem/index.vue
New file
@@ -0,0 +1,334 @@
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from "vue";
import { useDept } from "./utils/hook";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Delete from "~icons/ep/delete";
import EditPen from "~icons/ep/edit-pen";
import Refresh from "~icons/ep/refresh";
import AddFill from "~icons/ri/add-circle-line";
import { useUserStoreHook } from "@/store/modules/user";
defineOptions({
  name: "SystemDept"
});
const formRef = ref();
const tableRef = ref();
const {
  form,
  state,
  loading,
  columns,
  CGRcolumns,
  selectedNum,
  dataList,
  onSearch,
  resetForm,
  openDialog,
  handleDelete,
  handleSelectionChange,
  handleSizeChange,
  handleCurrentChange,
  pagination,
  checkboxAsRadio,
  onSelectionCancel,
  onbatchDel
} = useDept(tableRef);
function onFullscreen() {
  // 重置表格高度
  tableRef.value.setAdaptive();
}
const nowRole = computed(() => {
  return useUserStoreHook().nowRole;
});
onMounted(() => {});
</script>
<template>
  <div class="main">
    <!-- class="search-form bg-bg_color w-full pl-8 pt-[12px] overflow-auto" -->
    <el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
      <el-form ref="formRef" :model="form" labelWidth="100">
        <el-row>
          <!-- <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
            <el-form-item label="时间:">
              <el-date-picker
                v-model="form.createDateRange"
                type="daterange"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                value-format="YYYY-MM-DD HH:mm:ss"
                :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
                class="w-[100%]!"
              />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
            <el-form-item label="区域:">
              <el-cascader
                v-model="form.xingzhengquyu"
                class="w-full"
                :options="state.regionList"
                :props="{
                  value: 'code',
                  label: 'name',
                  children: 'regions'
                }"
                clearable
                filterable
                placeholder="请选择区域"
              />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label="行业品目:">
              <el-select
                v-model="form.hangyepinmu"
                placeholder="请选择行业品目"
                clearable
                class="w-[100%]!"
              >
                <el-option
                  v-for="item in state.hangyepingmuList"
                  :key="item.id"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label="项目进度:">
              <el-select
                v-model="form.orderStatus"
                placeholder="请选择项目进度"
                clearable
                class="w-[100%]!"
              >
                <el-option
                  v-for="item in state.orderStatusList"
                  :key="item.id"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item> </el-col
          ><el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label="质疑:">
              <el-checkbox-group
                v-model="form.zhiyi"
                clearable
                class="w-[100%]!"
                @change="checkboxAsRadio(form.zhiyi)"
              >
                <el-checkbox label="有" value="true" />
                <el-checkbox label="无" value="false" />
              </el-checkbox-group>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label="投诉:">
              <el-checkbox-group
                v-model="form.tousu"
                clearable
                class="w-[100%]!"
                @change="checkboxAsRadio(form.tousu)"
              >
                <el-checkbox label="有" value="true" />
                <el-checkbox label="无" value="false" />
              </el-checkbox-group>
            </el-form-item>
          </el-col> -->
          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label="项目名称:">
              <el-input
                v-model="form.projectName"
                placeholder="请输入项目名称"
                clearable
                class="w-[100%]!"
              />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label="代理机构:">
              <el-input
                v-model="form.dailijigoumingcheng"
                placeholder="请输入代理机构"
                clearable
                class="w-[100%]!"
              />
            </el-form-item>
          </el-col>
          <!-- <el-col
            v-if="nowRole.code == 'DLJG'"
            :xs="24"
            :sm="12"
            :md="8"
            :lg="6"
            :xl="4"
          >
            <el-form-item label="采购人:">
              <el-input
                v-model="form.caigourenmingcheng"
                placeholder="请输入采购人"
                clearable
                class="w-[100%]!"
              />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label="中标供应商:">
              <el-input
                v-model="form.zhongbiaoName"
                placeholder="请输入中标供应商"
                clearable
                class="w-[100%]!"
              />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label="评审专家:">
              <el-input
                v-model="form.zhuanjiaName"
                placeholder="请输入评审专家"
                clearable
                class="w-[100%]!"
              />
            </el-form-item>
          </el-col> -->
          <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
            <el-form-item label-width="40">
              <el-button type="primary" :loading="loading" @click="onSearch">
                搜索
              </el-button>
              <!-- <el-button
                :icon="useRenderIcon(Refresh)"
                @click="resetForm(formRef)"
              >
                重置
              </el-button> -->
              <!-- <el-button type="primary" @click="openDialog()"> 新增 </el-button> -->
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </el-card>
    <PureTableBar
      title=""
      :columns="nowRole.code == 'CGR' ? CGRcolumns : columns"
      :tableRef="tableRef?.getTableRef()"
      @refresh="onSearch"
      @fullscreen="onFullscreen"
    >
      <!-- <template #buttons>
        <el-button
          type="primary"
          :icon="useRenderIcon(AddFill)"
          @click="openDialog()"
        >
          新增项目
        </el-button>
      </template> -->
      <template v-slot="{ size, dynamicColumns }">
        <div
          v-if="selectedNum > 0"
          v-motion-fade
          class="bg-[var(--el-fill-color-light)] w-full h-[46px] mb-2 pl-4 flex items-center"
        >
          <div class="flex-auto">
            <span
              style="font-size: var(--el-font-size-base)"
              class="text-[rgba(42,46,54,0.5)] dark:text-[rgba(220,220,242,0.5)]"
            >
              已选 {{ selectedNum }} 项
            </span>
            <el-button type="primary" text @click="onSelectionCancel">
              取消选择
            </el-button>
          </div>
          <el-popconfirm title="是否确认删除?" @confirm="onbatchDel">
            <template #reference>
              <el-button type="danger" text class="mr-1!"> 批量删除 </el-button>
            </template>
          </el-popconfirm>
        </div>
        <pure-table
          ref="tableRef"
          adaptive
          :adaptiveConfig="{ offsetBottom: 45 }"
          align-whole="center"
          row-key="id"
          showOverflowTooltip
          table-layout="auto"
          :loading="loading"
          :data="dataList"
          :columns="dynamicColumns"
          :pagination="{ ...pagination, size }"
          :header-cell-style="{
            background: 'var(--el-fill-color-light)',
            color: 'var(--el-text-color-primary)'
          }"
          @selection-change="handleSelectionChange"
          @page-size-change="handleSizeChange"
          @page-current-change="handleCurrentChange"
        >
          <template #operation="{ row }">
            <el-button
              class="reset-margin"
              link
              type="primary"
              :size="size"
              :icon="useRenderIcon(EditPen)"
              @click="openDialog('修改', row)"
            />
            <!-- <el-button
              class="reset-margin"
              link
              type="primary"
              :size="size"
              :icon="useRenderIcon(AddFill)"
              @click="openDialog('新增', { parentId: row.id } as any)"
            >
              新增
            </el-button> -->
            <el-popconfirm
              :title="`是否确认删除项目名称为${row.projectName}的这条数据`"
              @confirm="handleDelete(row)"
            >
              <template #reference>
                <el-button
                  class="reset-margin"
                  link
                  type="primary"
                  :size="size"
                  :icon="useRenderIcon(Delete)"
                />
              </template>
            </el-popconfirm>
          </template>
        </pure-table>
      </template>
    </PureTableBar>
  </div>
</template>
<style lang="scss" scoped>
:deep(.el-table__inner-wrapper::before) {
  height: 0;
}
.main-content {
  margin: 24px 24px 0 !important;
}
.search-form {
  :deep(.el-form-item) {
    margin-bottom: 12px;
  }
}
</style>
src/views/system/aboutItem/utils/hook.tsx
New file
@@ -0,0 +1,489 @@
import dayjs from "dayjs";
import editForm from "../form.vue";
import { handleTree } from "@/utils/tree";
import { message } from "@/utils/message";
import { zhaobiaoPageOrder } from "@/api/item/index";
import {
  getCaigoufangshiList,
  getHangyepingmuList,
  getOrderStatusList,
  getRegionList,
  getDaimaleixingList,
  caigourenAdd,
  caigourenUpdate,
  caigourenDelete,
  caigourenBatchDelete
} from "@/api/item/index";
import { usePublicHooks } from "../../hooks";
import { addDialog } from "@/components/ReDialog";
import { type Ref, reactive, ref, onMounted, h, computed } from "vue";
import type { FormItemProps } from "./types";
import {
  cloneDeep,
  isAllEmpty,
  deviceDetection,
  getKeyList
} from "@pureadmin/utils";
import { useUserStoreHook } from "@/store/modules/user";
import type { PaginationProps } from "@pureadmin/table";
const nowRole = computed(() => {
  return useUserStoreHook().nowRole;
});
const selectedNum = ref(0);
export function useDept(tableRef: Ref) {
  const form = reactive({
    // 新增日期范围,可为 null,类型为数组
    createDateRange: null,
    // 行政区域,可为 null,类型为字符串
    xingzhengquyu: [],
    // 行业品目,可为 null,类型为字符串
    hangyepinmu: "",
    // 订单状态,可为 null,类型为 32 位整数
    orderStatus: "",
    // 质疑有无,可为 null,类型为布尔值
    zhiyi: [],
    // 投诉有无,可为 null,类型为布尔值
    tousu: [],
    // 项目名称,可为 null,类型为字符串
    projectName: null,
    // 代理机构名称,可为 null,类型为字符串
    dailijigoumingcheng: null,
    caigourenmingcheng: null,
    // 中标供应商姓名,可为 null,类型为字符串
    zhongbiaoName: null,
    // 专家姓名,可为 null,类型为字符串
    zhuanjiaName: null
  });
  const state = reactive({
    caigoufangshiList: [],
    hangyepingmuList: [],
    orderStatusList: [],
    regionList: [],
    daimaleixingList: []
  });
  const pagination = reactive<PaginationProps>({
    total: 0,
    pageSize: 10,
    currentPage: 1,
    background: true
  });
  //获取采购方式
  const getCaigoufangshiListFun = async () => {
    const res = await getCaigoufangshiList();
    state.caigoufangshiList = res.result;
  };
  //获取行业品目
  const getHangyepingmuListFun = async () => {
    const res = await getHangyepingmuList();
    state.hangyepingmuList = res.result;
  };
  //获取项目进度
  const getOrderStatusListFun = async () => {
    const res = await getOrderStatusList();
    state.orderStatusList = res.result;
  };
  // 获取区域
  const getRegionListFun = async () => {
    const res = await getRegionList();
    state.regionList = res.result;
  };
  // 获取代码类型
  const getDaimaleixingListFun = async () => {
    const res = await getDaimaleixingList();
    state.daimaleixingList = res.result;
  };
  const formRef = ref();
  const dataList = ref([]);
  const loading = ref(true);
  const { tagStyle } = usePublicHooks();
  const getOrderStatus = row => {
    const res = state.orderStatusList.find(item => {
      return row.orderStatus == item.status;
    });
    return res?.label;
  };
  const columns: TableColumnList = [
    {
      label: "勾选列", // 如果需要表格多选,此处label必须设置
      type: "selection",
      fixed: "left",
      reserveSelection: true // 数据刷新后保留选项
    },
    {
      label: "采购人",
      prop: "caigourenmingcheng",
      minWidth: 70
    },
    {
      label: "项目名称",
      prop: "projectName",
      width: 180,
      align: "left"
    },
    {
      label: "项目进度",
      prop: "orderStatus",
      minWidth: 70,
      cellRenderer: ({ row, props }) => getOrderStatus(row)
    },
    {
      label: "报名费",
      prop: "baomingfei",
      minWidth: 70
    },
    {
      label: "投标保证金",
      prop: "toubiaobaozhengjin",
      minWidth: 70
    },
    {
      label: "中标供应商",
      prop: "zhongbiaoName",
      minWidth: 180
    },
    {
      label: "评审专家",
      prop: "zhuanjiaName",
      minWidth: 70
    },
    {
      label: "质疑",
      prop: "zhiyi",
      minWidth: 100,
      cellRenderer: ({ row, props }) => (
        <span>{row.status === 1 ? "有" : "无"}</span>
      )
    },
    {
      label: "投诉",
      prop: "tousu",
      minWidth: 100,
      cellRenderer: ({ row, props }) => (
        // <el-tag size={props.size} style={tagStyle.value(row.status)}>
        <span>{row.status === 1 ? "有" : "无"}</span>
        // </el-tag>
      )
    },
    {
      label: "操作",
      fixed: "right",
      width: 80,
      slot: "operation"
    }
  ];
  const CGRcolumns: TableColumnList = [
    {
      label: "勾选列", // 如果需要表格多选,此处label必须设置
      type: "selection",
      fixed: "left",
      reserveSelection: true // 数据刷新后保留选项
    },
    {
      label: "代理机构",
      prop: "dailijigoumingcheng",
      minWidth: 70
    },
    {
      label: "项目名称",
      prop: "projectName",
      width: 180,
      align: "left"
    },
    {
      label: "项目进度",
      prop: "orderStatus",
      minWidth: 70,
      cellRenderer: ({ row, props }) => getOrderStatus(row)
    },
    {
      label: "报名费",
      prop: "baomingfei",
      minWidth: 70
    },
    {
      label: "投标保证金",
      prop: "toubiaobaozhengjin",
      minWidth: 70
    },
    {
      label: "中标供应商",
      prop: "zhongbiaoName",
      minWidth: 180
    },
    {
      label: "评审专家",
      prop: "zhuanjiaName",
      minWidth: 70
    },
    {
      label: "质疑",
      prop: "zhiyi",
      minWidth: 100,
      cellRenderer: ({ row, props }) => (
        <span>{row.status === 1 ? "有" : "无"}</span>
      )
    },
    {
      label: "投诉",
      prop: "tousu",
      minWidth: 100,
      cellRenderer: ({ row, props }) => (
        // <el-tag size={props.size} style={tagStyle.value(row.status)}>
        <span>{row.status === 1 ? "有" : "无"}</span>
        // </el-tag>
      )
    },
    {
      label: "操作",
      fixed: "right",
      width: 80,
      slot: "operation"
    }
  ];
  /** 当CheckBox选择项发生变化时会触发该事件 */
  function handleSelectionChange(val) {
    selectedNum.value = val.length;
    // 重置表格高度
    tableRef.value.setAdaptive();
  }
  /** 取消选择 */
  function onSelectionCancel() {
    selectedNum.value = 0;
    // 用于多选表格,清空用户的选择
    tableRef.value.getTableRef().clearSelection();
  }
  /** 批量删除 */
  async function onbatchDel() {
    // 返回当前选中的行
    const curSelected = tableRef.value.getTableRef().getSelectionRows();
    const data = [];
    curSelected.forEach(item => {
      data.push({ id: item.id });
    });
    const res = await caigourenBatchDelete(data);
    if (res.code == "200") {
      // 接下来根据实际业务,通过选中行的某项数据,比如下面的id,调用接口进行批量删除
      message(
        `已删除项目名称为 ${getKeyList(curSelected, "projectName")} 的数据`,
        {
          type: "success"
        }
      );
      onSearch();
    } else {
      message(res.message, {
        type: "error"
      });
    }
    tableRef.value.getTableRef().clearSelection();
    onSearch();
  }
  function handleSizeChange(val: number) {
    console.log(`${val} items per page`);
  }
  function handleCurrentChange(val: number) {
    console.log(`current page: ${val}`);
  }
  function resetForm(formEl) {
    if (!formEl) return;
    formEl.resetFields();
    onSearch();
  }
  const checkboxAsRadio = data => {
    if (data.length > 1) {
      data.shift();
    }
  };
  async function onSearch() {
    const obj = cloneDeep(form);
    obj.tousu = obj.tousu.join("");
    obj.zhiyi = obj.zhiyi.join("");
    obj.xingzhengquyu = obj.xingzhengquyu ? obj.xingzhengquyu.join("") : "";
    loading.value = true;
    const { result } = await zhaobiaoPageOrder(obj); // 这里是返回一维数组结构,前端自行处理成树结构,返回格式要求:唯一id加父节点parentId,parentId取父节点id
    const newData = result.items;
    loading.value = false;
    pagination.total = result.total;
    pagination.pageSize = result.pageSize;
    pagination.currentPage = result.page;
    // if (!isAllEmpty(form.name)) {
    //   // 前端搜索项目名称
    //   newData = newData.filter(item => item.name.includes(form.name));
    // }
    // if (!isAllEmpty(form.status)) {
    //   // 前端搜索状态
    //   newData = newData.filter(item => item.status === form.status);
    // }
    dataList.value = handleTree(newData); // 处理成树结构
  }
  function formatHigherDeptOptions(treeList) {
    // 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级项目级联选择器的展示(实际开发中也是如此,不可能前端需要的每个字段后端都会返回,这时需要前端自行根据后端返回的某些字段做逻辑处理)
    if (!treeList || !treeList.length) return;
    const newTreeList = [];
    for (let i = 0; i < treeList.length; i++) {
      treeList[i].disabled = treeList[i].status === 0 ? true : false;
      formatHigherDeptOptions(treeList[i].children);
      newTreeList.push(treeList[i]);
    }
    return newTreeList;
  }
  function openDialog(title = "新增", row?: FormItemProps) {
    console.log(row, "-");
    addDialog({
      title: `${title}项目`,
      props: {
        formInline: {
          higherDeptOptions: formatHigherDeptOptions(cloneDeep(dataList.value)),
          id: row?.id ?? "",
          projectCode: row?.projectCode ?? "", // 项目编号(必填)
          projectName: row?.projectName ?? "", // 项目名称(必填)
          hangyepinmu: row?.hangyepinmu ?? null, // 行业品目(可选)
          caigoufangshi: row?.caigoufangshi ?? null, // 采购方式(可选)
          caigouyusuan: row?.caigouyusuan ?? null, // 采购预算(可选)
          dingbiaoguize: row?.dingbiaoguize ?? null, // 定标规则(可选)
          baomingfei: row?.baomingfei ?? null, // 报名费(可选)
          toubiaobaozhengjin: row?.toubiaobaozhengjin ?? null, // 投标保证金(可选)
          lianhetitoubiao: row?.lianhetitoubiao ?? null, // 联合体投标(可选)
          kaibiaofangshi: row?.kaibiaofangshi ?? null, // 开标方式(可选)
          shifoufenbao: row?.shifoufenbao ?? "false", // 是否分包(可选)
          shifoutuisongxuanchuan: row?.shifoutuisongxuanchuan ?? "true", // 是否推送宣传(可选)
          caigourenmingcheng: row?.caigourenmingcheng ?? null, // 采购人名称(可选)
          xingzhengquyu: row?.xingzhengquyu.split(",") ?? [], // 行政区域(可选)
          xingzhengquyuName: row?.xingzhengquyuName ?? null, // 行政区域名称(可选)
          jigoudaima: row?.jigoudaima ?? null, // 机构代码(可选)
          daimaleixing: row?.daimaleixing ?? null, // 代码类型(可选)
          lianxiren: row?.lianxiren ?? null, // 联系人(可选)
          lianxidianhua: row?.lianxidianhua ?? null, // 联系电话(可选)
          tongxindizhi: row?.tongxindizhi ?? null, // 通信地址(可选)
          dianziyoujian: row?.dianziyoujian ?? null, // 电子邮件(可选)
          xiangmujingbanren: row?.xiangmujingbanren ?? null, // 项目经办人(可选)
          zhiwu: row?.zhiwu ?? null, // 职务(可选)
          jingbanrendianhua: row?.jingbanrendianhua ?? null, // 经办人电话(可选)
          dailijigoumingcheng: row?.dailijigoumingcheng ?? null, // 代理机构名称(可选)
          dailiLianxiren: row?.dailiLianxiren ?? null, // 代理机构联系人(可选)
          dailiLianxidianhua: row?.dailiLianxidianhua ?? null, // 代理机构联系电话(可选)
          dailiDianziyoujian: row?.dailiDianziyoujian ?? null, // 代理机构电子邮件(可选)
          dailiTongxindizhi: row?.dailiTongxindizhi ?? null, // 代理机构通信地址(可选)
          dailiXiangmujingli: row?.dailiXiangmujingli ?? null, // 代理机构项目经理(可选
          dailijingliLianxidianhua: row?.dailijingliLianxidianhua ?? null // 代理机构项目经理联系电话(可选)
        }
      },
      width: "80%",
      draggable: true,
      fullscreen: deviceDetection(),
      fullscreenIcon: true,
      sureBtnLoading: true,
      closeOnClickModal: false,
      contentRenderer: () => h(editForm, { ref: formRef, formInline: null }),
      beforeSure: (done, { options, closeLoading }) => {
        const FormRef = formRef.value.getRef();
        const curData = cloneDeep(options.props.formInline as FormItemProps);
        async function chores() {
          message(`您${title}了项目名称为${curData.projectName}的这条数据`, {
            type: "success"
          });
          // curData.dingbiaoguize = curData.dingbiaoguize.join("");
          curData.xingzhengquyu = curData.xingzhengquyu.join(",");
          let res;
          if (title == "新增") {
            res = await caigourenAdd(curData);
          } else {
            res = await caigourenUpdate(curData);
          }
          if (res.code == "200") {
            done(); // 关闭弹框
            onSearch(); // 刷新表格数据
          } else {
            closeLoading();
            message(res.message, {
              type: "error"
            });
          }
        }
        FormRef.validate((valid, obj) => {
          if (valid) {
            // 表单规则校验通过
            if (title === "新增") {
              // 实际开发先调用新增接口,再进行下面操作
              chores();
            } else {
              // 实际开发先调用修改接口,再进行下面操作
              chores();
            }
          } else {
            closeLoading();
            const fail = [];
            for (const key in obj) {
              fail.push(obj[key][0].message);
            }
            message(fail[0], {
              type: "warning"
            });
            return false;
          }
        });
      }
    });
  }
  async function handleDelete(row) {
    const res = await caigourenDelete({ id: row.id });
    if (res.code == "200") {
      message(`您删除了项目名称为${row.projectName}的这条数据`, {
        type: "success"
      });
      onSearch();
    } else {
      message(res.message, {
        type: "error"
      });
    }
  }
  onMounted(() => {
    onSearch();
    getCaigoufangshiListFun();
    getHangyepingmuListFun();
    getOrderStatusListFun();
    getRegionListFun();
    getDaimaleixingListFun();
  });
  return {
    form,
    state,
    loading,
    columns,
    CGRcolumns,
    dataList,
    selectedNum,
    /** 搜索 */
    onSearch,
    /** 重置 */
    resetForm,
    /** 新增、修改项目 */
    openDialog,
    /** 删除项目 */
    handleDelete,
    handleSelectionChange,
    handleSizeChange,
    handleCurrentChange,
    pagination,
    checkboxAsRadio,
    onSelectionCancel,
    onbatchDel
  };
}
src/views/system/aboutItem/utils/rule.ts
New file
@@ -0,0 +1,222 @@
import { reactive } from "vue";
import type { FormRules } from "element-plus";
import { isPhone, isEmail } from "@pureadmin/utils";
/** 自定义表单规则校验 */
export const formRules = reactive(<FormRules>{
  // 项目编号(必填)
  projectCode: [
    { required: true, message: "请输入项目编号", trigger: "blur" },
    { max: 50, message: "项目编号长度不能超过50个字符", trigger: "blur" }
  ],
  // 项目名称(必填)
  projectName: [
    { required: true, message: "请输入项目名称", trigger: "blur" },
    { max: 200, message: "项目名称长度不能超过200个字符", trigger: "blur" }
  ],
  // 行业品目(可选,但选择时需校验)
  hangyepinmu: [
    { required: true, message: "请选择行业品目", trigger: "blur" },
    { type: "string", message: "行业品目格式不正确", trigger: "change" }
  ],
  // 采购方式(可选,但选择时需校验)
  caigoufangshi: [
    { required: true, message: "请选择采购方式", trigger: "blur" },
    { type: "string", message: "采购方式格式不正确", trigger: "change" }
  ],
  // 采购预算(可选,需为数字)
  caigouyusuan: [
    { required: true, message: "请输入采购预算", trigger: "blur" }
    // { type: "number", message: "采购预算必须为数字", trigger: "blur" },
    // { min: 0, message: "采购预算不能为负数", trigger: "blur" }
  ],
  // 定标规则(可选)
  dingbiaoguize: [
    { required: true, message: "请选择定标规则", trigger: "blur" },
    { type: "string", message: "定标规则格式不正确", trigger: "change" }
  ],
  // 报名费(可选,需为数字)
  baomingfei: [
    { required: true, message: "请输入报名费", trigger: "blur" }
    // { type: "number", message: "报名费必须为数字", trigger: "blur" },
    // { min: 0, message: "报名费不能为负数", trigger: "blur" }
  ],
  // 投标保证金(可选,需为数字)
  toubiaobaozhengjin: [
    { required: true, message: "请输入投标保证金费", trigger: "blur" }
    // { type: "number", message: "投标保证金必须为数字", trigger: "blur" },
    // { min: 0, message: "投标保证金不能为负数", trigger: "blur" }
  ],
  // 联合体投标(可选,需为布尔值)
  lianhetitoubiao: [
    { required: true, message: "请选择联合体投标", trigger: "blur" }
    // { type: "boolean", message: "联合体投标必须为布尔值", trigger: "change" }
  ],
  // 开标方式(可选)
  kaibiaofangshi: [
    { required: true, message: "请选择开标方式", trigger: "blur" }
    // { type: "string", message: "开标方式格式不正确", trigger: "change" }
  ],
  // 是否分包(可选,需为布尔值)
  shifoufenbao: [
    { required: true }
    // { type: "boolean", message: "是否分包必须为布尔值", trigger: "change" }
  ],
  // 是否推送宣传(可选,需为布尔值)
  shifoutuisongxuanchuan: [
    { required: true }
    // { type: "boolean", message: "是否推送宣传必须为布尔值", trigger: "change" }
  ],
  // 采购人名称(可选)
  caigourenmingcheng: [
    { required: true, message: "请输入采购人名称", trigger: "blur" },
    { max: 100, message: "采购人名称长度不能超过100个字符", trigger: "blur" }
  ],
  // 行政区域(可选,需为数组)
  xingzhengquyu: [
    { required: true, message: "请选择行政区域", trigger: "blur" },
    { type: "array", message: "行政区域必须为数组格式", trigger: "change" }
  ],
  // 行政区域名称(可选)
  // xingzhengquyuName: [
  //   { required: false },
  //   { max: 100, message: "行政区域名称长度不能超过100个字符", trigger: "blur" }
  // ],
  // 机构代码(可选,验证格式)
  jigoudaima: [
    { required: true, message: "请输入机构代码", trigger: "blur" }
    // {
    //   pattern: /^[A-Z0-9]{8}-[A-Z0-9]{1}$/,
    //   message: "机构代码格式不正确",
    //   trigger: "blur"
    // }
  ],
  // 代码类型(可选)
  daimaleixing: [
    { required: true, message: "请选择代码类型", trigger: "blur" },
    { type: "string", message: "代码类型格式不正确", trigger: "change" }
  ],
  // 联系人(可选)
  lianxiren: [
    { required: true, message: "请输入联系人", trigger: "blur" },
    { max: 50, message: "联系人姓名长度不能超过50个字符", trigger: "blur" }
  ],
  // 联系电话(可选,验证手机号格式)
  lianxidianhua: [
    { required: true, message: "请输入联系人电话", trigger: "blur" },
    {
      pattern: /^1[3-9]\d{9}$/,
      message: "请输入正确的手机号码",
      trigger: "blur"
    }
  ],
  // 通信地址(可选)
  tongxindizhi: [
    { required: true, message: "请输入通信地址", trigger: "blur" },
    { max: 200, message: "通信地址长度不能超过200个字符", trigger: "blur" }
  ],
  // 电子邮件(可选,验证邮箱格式)
  dianziyoujian: [
    { required: true, message: "请输入电子邮件", trigger: "blur" },
    { type: "email", message: "请输入正确的邮箱地址", trigger: "blur" }
  ],
  // 项目经办人(可选)
  xiangmujingbanren: [
    { required: true, message: "请输入项目经办人", trigger: "blur" },
    { max: 50, message: "项目经办人姓名长度不能超过50个字符", trigger: "blur" }
  ],
  // 职务(可选)
  zhiwu: [
    { required: true, message: "请输入职务", trigger: "blur" },
    { max: 50, message: "职务名称长度不能超过50个字符", trigger: "blur" }
  ],
  // 经办人电话(可选,验证手机号格式)
  jingbanrendianhua: [
    { required: true, message: "请输入经办人电话", trigger: "blur" },
    {
      pattern: /^1[3-9]\d{9}$/,
      message: "请输入正确的手机号码",
      trigger: "blur"
    }
  ],
  // 代理机构名称(可选)
  dailijigoumingcheng: [
    { required: true, message: "请输入代理机构名称", trigger: "blur" },
    { max: 100, message: "代理机构名称长度不能超过100个字符", trigger: "blur" }
  ],
  // 代理机构联系人(可选)
  dailiLianxiren: [
    { required: true, message: "请输入联系人", trigger: "blur" },
    {
      max: 50,
      message: "联系人姓名长度不能超过50个字符",
      trigger: "blur"
    }
  ],
  // 代理机构联系电话(可选,验证手机号格式)
  dailiLianxidianhua: [
    { required: true, message: "请输入联系电话", trigger: "blur" },
    {
      pattern: /^1[3-9]\d{9}$/,
      message: "请输入正确的手机号码",
      trigger: "blur"
    }
  ],
  // 代理机构电子邮件(可选,验证邮箱格式)
  dailiDianziyoujian: [
    { required: true, message: "请输入电子邮件", trigger: "blur" },
    { type: "email", message: "请输入正确的邮箱地址", trigger: "blur" },
    {
      validator: (rule, value, callback) => {
        if (value === "") {
          callback();
        } else if (!isEmail(value)) {
          callback(new Error("请输入正确的邮箱格式"));
        } else {
          callback();
        }
      },
      trigger: "blur"
    }
  ],
  // 代理机构通信地址(可选)
  dailiTongxindizhi: [
    { required: true, message: "请输入通信地址", trigger: "blur" },
    {
      max: 200,
      message: "通信地址长度不能超过200个字符",
      trigger: "blur"
    }
  ],
  // 代理机构项目经理(可选)
  dailiXiangmujingli: [
    { required: true, message: "请输入项目经理", trigger: "blur" },
    {
      max: 50,
      message: "项目经理姓名长度不能超过50个字符",
      trigger: "blur"
    }
  ],
  // 代理机构项目经理联系电话(可选,验证手机号格式)
  dailijingliLianxidianhua: [
    { required: true, message: "请输入联系电话", trigger: "blur" },
    {
      pattern: /^1[3-9]\d{9}$/,
      message: "请输入正确的手机号码",
      trigger: "blur"
    },
    {
      validator: (rule, value, callback) => {
        if (value === "") {
          callback();
        } else if (!isPhone(value)) {
          callback(new Error("请输入正确的手机号码格式"));
        } else {
          callback();
        }
      },
      trigger: "blur"
      // trigger: "click" // 如果想在点击确定按钮时触发这个校验,trigger 设置成 click 即可
    }
  ]
});
src/views/system/aboutItem/utils/types.ts
New file
@@ -0,0 +1,39 @@
interface FormItemProps {
  id: string;
  projectCode: string; // 项目编号(必填)
  projectName: string; // 项目名称(必填)
  hangyepinmu: any | null; // 行业品目(可选)
  caigoufangshi: any | null; // 采购方式(可选)
  caigouyusuan: any | null; // 采购预算(可选)
  dingbiaoguize: any | null; // 定标规则(可选)
  baomingfei: any | null; // 报名费(可选)
  toubiaobaozhengjin: any | null; // 投标保证金(可选)
  lianhetitoubiao: any | null; // 联合体投标(可选)
  kaibiaofangshi: any | null; // 开标方式(可选)
  shifoufenbao: any | null; // 是否分包(可选)
  shifoutuisongxuanchuan: any | null; // 是否推送宣传(可选)
  caigourenmingcheng: string | null; // 采购人名称(可选)
  xingzhengquyu: any | null; // 行政区域(可选)
  xingzhengquyuName: string | null; // 行政区域名称(可选)
  jigoudaima: string | null; // 机构代码(可选)
  daimaleixing: any | null; // 代码类型(可选)
  lianxiren: string | null; // 联系人(可选)
  lianxidianhua: string | null; // 联系电话(可选)
  tongxindizhi: string | null; // 通信地址(可选)
  dianziyoujian: string | null; // 电子邮件(可选)
  xiangmujingbanren: string | null; // 项目经办人(可选)
  zhiwu: string | null; // 职务(可选)
  jingbanrendianhua: string | null; // 经办人电话(可选)
  dailijigoumingcheng: string | null; // 代理机构名称(可选)
  dailiLianxiren: string | null; // 代理机构联系人(可选)
  dailiLianxidianhua: string | null; // 代理机构联系电话(可选)
  dailiDianziyoujian: string | null; // 代理机构电子邮件(可选)
  dailiTongxindizhi: string | null; // 代理机构通信地址(可选)
  dailiXiangmujingli: string | null; // 代理机构项目经理(可选)
  dailijingliLianxidianhua: string | null; // 代理机构项目经理联系电话(可选)
}
interface FormProps {
  formInline: FormItemProps;
}
export type { FormItemProps, FormProps };
src/views/system/dept/index.vue
@@ -306,7 +306,7 @@
              新增
            </el-button> -->
            <el-popconfirm
              :title="`是否确认删除部门名称为${row.projectName}的这条数据`"
              :title="`是否确认删除项目名称为${row.projectName}的这条数据`"
              @confirm="handleDelete(row)"
            >
              <template #reference>
src/views/system/dept/utils/hook.tsx
@@ -18,7 +18,7 @@
import { usePublicHooks } from "../../hooks";
import { addDialog } from "@/components/ReDialog";
import { type Ref, reactive, ref, onMounted, h, computed } from "vue";
import type { FormItemProps } from "../utils/types";
import type { FormItemProps } from "./types";
import {
  cloneDeep,
  isAllEmpty,
@@ -317,7 +317,7 @@
    pagination.pageSize = result.pageSize;
    pagination.currentPage = result.page;
    // if (!isAllEmpty(form.name)) {
    //   // 前端搜索部门名称
    //   // 前端搜索项目名称
    //   newData = newData.filter(item => item.name.includes(form.name));
    // }
    // if (!isAllEmpty(form.status)) {
@@ -328,7 +328,7 @@
  }
  function formatHigherDeptOptions(treeList) {
    // 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级部门级联选择器的展示(实际开发中也是如此,不可能前端需要的每个字段后端都会返回,这时需要前端自行根据后端返回的某些字段做逻辑处理)
    // 根据返回数据的status字段值判断追加是否禁用disabled字段,返回处理后的树结构,用于上级项目级联选择器的展示(实际开发中也是如此,不可能前端需要的每个字段后端都会返回,这时需要前端自行根据后端返回的某些字段做逻辑处理)
    if (!treeList || !treeList.length) return;
    const newTreeList = [];
    for (let i = 0; i < treeList.length; i++) {
@@ -474,9 +474,9 @@
    onSearch,
    /** 重置 */
    resetForm,
    /** 新增、修改部门 */
    /** 新增、修改项目 */
    openDialog,
    /** 删除部门 */
    /** 删除项目 */
    handleDelete,
    handleSelectionChange,
    handleSizeChange,