Michael Wang 3 anni fa
parent
commit
0a87666aa6

+ 4 - 0
components.d.ts

@@ -24,7 +24,11 @@ declare module 'vue' {
     ATabPane: typeof import('ant-design-vue/es')['TabPane']
     ATabs: typeof import('ant-design-vue/es')['Tabs']
     CourseTypeSelect: typeof import('./src/components/CourseTypeSelect.vue')['default']
+    'CourseTypeSelect copy': typeof import('./src/components/CourseTypeSelect copy.vue')['default']
     Layout: typeof import('./src/components/Layout.vue')['default']
+    PaperTypeSelect: typeof import('./src/components/PaperTypeSelect.vue')['default']
+    ProjectStatusSelect: typeof import('./src/components/ProjectStatusSelect.vue')['default']
+    'ProjectStatusSelect copy': typeof import('./src/components/ProjectStatusSelect copy.vue')['default']
     QmButton: typeof import('./src/components/QmButton.vue')['default']
     RoleSelect: typeof import('./src/components/RoleSelect.vue')['default']
     RootOrgSelect: typeof import('./src/components/RootOrgSelect.vue')['default']

+ 29 - 0
src/api/projectManagementPage.ts

@@ -0,0 +1,29 @@
+import { httpApp } from "@/plugins/axiosApp";
+
+/** 项目分页查询 */
+export function getProjectList(params: {
+  status?: string;
+  name?: string;
+  rootOrgId: number;
+  pageNo?: number;
+  pageSize?: number;
+}) {
+  return httpApp.post("/api/ess/project/page", params);
+}
+
+/** 更新项目 */
+export function updateProject(params: {
+  name?: string;
+  id?: number;
+  rootOrgId?: number;
+}) {
+  return httpApp.post("/api/ess/project/save", params);
+}
+
+/** 删除项目 */
+export function deleteProjects(ids: number[]) {
+  return httpApp.post(
+    `/api/ess/project/delete`,
+    new URLSearchParams([["ids", ids.join(",")]])
+  );
+}

+ 8 - 2
src/components/Layout.vue

@@ -35,8 +35,14 @@
         <a-sub-menu key="sub2">
           <template #icon> icon </template>
           <template #title>项目管理</template>
-          <a-menu-item key="21">项目列表</a-menu-item>
-          <a-menu-item key="22">关联分析</a-menu-item>
+          <a-menu-item key="21">
+            <router-link
+              active-class="active-route"
+              to="/project/projectManagement"
+            >
+              项目列表
+            </router-link>
+          </a-menu-item>
         </a-sub-menu>
       </a-menu>
     </div>

+ 41 - 0
src/components/PaperTypeSelect.vue

@@ -0,0 +1,41 @@
+<template>
+  <a-select
+    placeholder="分析状态"
+    allowClear
+    :disabled="props.disabled"
+    :value="valueStr"
+    @change="handleChange"
+    style="width: 120px"
+  >
+    <a-select-option v-for="(item, index) in optionList" :key="index" :value="item">
+      {{ item }}
+    </a-select-option>
+  </a-select>
+</template>
+
+<script setup lang="ts">
+import { computed } from "vue-demi";
+
+const optionList = ["ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
+
+const props = withDefaults(
+  defineProps<{
+    value?: string;
+    disabled?: boolean;
+  }>(),
+  {
+    value: undefined,
+    disabled: false,
+  }
+);
+const emit = defineEmits(["update:value"]);
+
+const valueStr = computed(() => {
+  let res: undefined | string = props.value ?? undefined;
+  return res as undefined | string;
+});
+
+function handleChange(v: undefined | string) {
+  emit("update:value", v);
+}
+</script>

+ 44 - 0
src/components/ProjectStatusSelect.vue

@@ -0,0 +1,44 @@
+<template>
+  <a-select
+    placeholder="分析状态"
+    allowClear
+    :disabled="props.disabled"
+    :value="valueStr"
+    @change="handleChange"
+    style="width: 120px"
+  >
+    <a-select-option
+      v-for="(item, index) in PROJECT_STATUS"
+      :key="index"
+      :value="item.code"
+    >
+      {{ item.name }}
+    </a-select-option>
+  </a-select>
+</template>
+
+<script setup lang="ts">
+import { PROJECT_STATUS } from "@/constants/constants";
+import { computed } from "vue-demi";
+
+const props = withDefaults(
+  defineProps<{
+    value?: string;
+    disabled?: boolean;
+  }>(),
+  {
+    value: undefined,
+    disabled: false,
+  }
+);
+const emit = defineEmits(["update:value"]);
+
+const valueStr = computed(() => {
+  let res: undefined | string = props.value ?? undefined;
+  return res as undefined | string;
+});
+
+function handleChange(v: undefined | string) {
+  emit("update:value", v);
+}
+</script>

+ 23 - 0
src/constants/constants.ts

@@ -7,3 +7,26 @@ if (!localStorage.getItem("deviceId")) {
   localStorage.setItem("deviceId", MD5(Math.random() + "-" + Date.now()));
 }
 export const DEVICE_ID = localStorage.getItem("deviceId");
+
+export const PROJECT_STATUS = [
+  {
+    name: "未开始",
+    code: "NONE",
+  },
+  {
+    name: "进行中",
+    code: "PROCESSING",
+  },
+  {
+    name: "已完成",
+    code: "FINISH",
+  },
+  {
+    name: "任务失败",
+    code: "FAIL",
+  },
+  {
+    name: "停止中",
+    code: "STOPING",
+  },
+];

+ 1 - 1
src/features/courseManagement/CourseManagement.vue

@@ -146,7 +146,7 @@ import {
 import { useMainStore } from "@/store";
 import { Course_Type } from "@/types";
 import { downloadFileURL } from "@/utils/utils";
-import { message, Modal } from "ant-design-vue";
+import { message } from "ant-design-vue";
 import { watch, onMounted, ref, reactive, toRaw } from "vue-demi";
 
 const store = useMainStore();

+ 213 - 0
src/features/projectManagement/ProjectManagement.vue

@@ -0,0 +1,213 @@
+<template>
+  <div>
+    <div class="tw-bg-white tw-p-5 tw-rounded-xl tw-mb-5">
+      <span class="tw-mr-4"></span>
+      <a-input
+        v-model:value="name"
+        class="tw-mr-4"
+        style="width: 178px"
+        placeholder="项目名称"
+        allowClear
+      ></a-input>
+
+      <span class="tw-mr-4"></span>
+      <ProjectStatusSelect v-model:value="projectStatus" />
+      <span class="tw-mr-4"></span>
+      <a-button @click="search">查询</a-button>
+
+      <div class="tw-mt-4">
+        <a-button @click="newProject">新增</a-button>
+        <a-button @click="handleDeleteProjects(selectIds)"> 批量删除 </a-button>
+      </div>
+    </div>
+
+    <div class="tw-bg-white tw-p-5 tw-rounded-xl">
+      <a-table
+        row-key="id"
+        :columns="columns"
+        :data-source="data"
+        :row-selection="rowSelection"
+        :pagination="{
+          pageSize: pageSize,
+          current: pageNo,
+          total: totalElements,
+          showTotal: (total: number) => `总数:${total}`,
+          onChange: (pageNoChanged: number, pageSizeChanged: number) => {
+            pageNo = pageNoChanged; 
+            pageSize = pageSizeChanged;
+          }
+        }"
+      >
+        <template #status="{ text }">
+          <a>{{ $filters.projectStatusFilter(text) }}</a>
+        </template>
+        <template #action="{ record }">
+          <span>
+            <a-button @click="showModal(record)">编辑</a-button>
+            <a-button @click="handleDeleteProjects([record.id])">
+              删除
+            </a-button>
+          </span>
+        </template>
+      </a-table>
+    </div>
+
+    <a-modal
+      v-model:visible="visible"
+      title="项目信息页"
+      @ok="handleOk"
+      ok-text="确定"
+      cancel-text="取消"
+    >
+      <a-form>
+        <a-form-item v-show="projectObj.id" label="项目id">
+          <a-input
+            :disabled="!!projectObj.id"
+            v-model:value="projectObj.id"
+          ></a-input>
+        </a-form-item>
+        <a-form-item label="项目名称">
+          <a-input v-model:value="projectObj.name"></a-input>
+        </a-form-item>
+      </a-form>
+    </a-modal>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {
+  deleteProjects,
+  getProjectList,
+  updateProject,
+} from "@/api/projectManagementPage";
+import { useMainStore } from "@/store";
+import { message } from "ant-design-vue";
+import { watch, onMounted, ref, reactive, toRaw } from "vue-demi";
+
+const store = useMainStore();
+store.currentLocation = "基础管理 / 项目列表";
+
+let rootOrgId = $ref(undefined as unknown as number);
+let name = $ref("");
+let projectStatus = $ref(undefined as undefined | string);
+
+let data = $ref([]);
+let pageSize = $ref(10);
+let pageNo = $ref(1);
+let totalElements = $ref(0);
+
+async function search() {
+  await fetchData();
+}
+
+watch(() => [pageNo, pageSize], fetchData);
+
+async function fetchData() {
+  const res = await getProjectList({
+    name,
+    status: projectStatus,
+    rootOrgId,
+    pageSize,
+    pageNo,
+  });
+  // console.log(res);
+  data = res.data.content;
+  pageNo = res.data.pageNo;
+  pageSize = res.data.pageSize;
+  totalElements = res.data.totalElements;
+}
+
+const columns = [
+  {
+    title: "项目id",
+    dataIndex: "id",
+    width: 80,
+  },
+  {
+    title: "项目名称",
+    dataIndex: "name",
+    width: 150,
+  },
+  {
+    title: "分析状态",
+    dataIndex: "status",
+    slots: { customRender: "status" },
+  },
+  {
+    title: "创建时间",
+    dataIndex: "createTime",
+  },
+  {
+    title: "创建人",
+    dataIndex: "creator",
+  },
+  {
+    title: "更新时间",
+    dataIndex: "updateTime",
+  },
+  {
+    title: "更新人",
+    dataIndex: "updater",
+  },
+  {
+    title: "操作",
+    key: "action",
+    slots: { customRender: "action" },
+  },
+];
+
+onMounted(async () => {
+  rootOrgId = store.userInfo.rootOrgId;
+  await search();
+});
+
+const visible = ref<boolean>(false);
+
+const showModal = (record: any) => {
+  Object.assign(projectObj, record);
+  visible.value = true;
+};
+
+const handleOk = async (e: MouseEvent) => {
+  await updateProject(toRaw(projectObj));
+  visible.value = false;
+  await search();
+};
+
+const initProject = {
+  id: undefined,
+  code: "",
+  name: "",
+  enable: true,
+  type: undefined,
+  rootOrgId: store.userInfo.rootOrgId,
+};
+const projectObj = reactive({ ...initProject });
+
+const newProject = async () => {
+  Object.assign(projectObj, initProject);
+  showModal(projectObj);
+};
+
+function checkEmpty(selectIds: number[]): boolean {
+  if (selectIds && selectIds.length > 0) {
+    return false;
+  } else {
+    message.warn({ content: "请先选择行" });
+    return true;
+  }
+}
+async function handleDeleteProjects(ids: number[]) {
+  if (checkEmpty(ids)) return;
+  await deleteProjects(ids);
+  await search();
+}
+
+let selectIds = $ref<number[]>([]);
+const rowSelection = {
+  onChange: (selectedRowKeys: (string | number)[]) => {
+    console.log(`selectedRowKeys: ${selectedRowKeys}`);
+    selectIds = selectedRowKeys as number[];
+  },
+};
+</script>

+ 5 - 1
src/filters/index.ts

@@ -1,4 +1,4 @@
-import { YYYYMMDDHHmmss } from "@/constants/constants";
+import { PROJECT_STATUS, YYYYMMDDHHmmss } from "@/constants/constants";
 import moment from "moment";
 
 export default {
@@ -14,4 +14,8 @@ export default {
     if (typeof val !== "string") return "无";
     return { PUBLIC: "公共科目", MAJOR: "专业科目" }[val + ""];
   },
+  projectStatusFilter(val: string) {
+    if (typeof val !== "string") return "无";
+    return PROJECT_STATUS.find((p) => p.code === val)?.name;
+  },
 };

+ 11 - 0
src/router/index.ts

@@ -43,6 +43,17 @@ const routes = [
     ],
     component: Layout,
   },
+  {
+    path: "/project",
+    children: [
+      {
+        path: "projectManagement",
+        component: () =>
+          import("@/features/projectManagement/ProjectManagement.vue"),
+      },
+    ],
+    component: Layout,
+  },
   {
     path: "/:pathMatch(.*)*",
     name: "NotFound",