zhangyu 4 rokov pred
rodič
commit
c4ecf7a68d

+ 33 - 0
src/api/datacenter.ts

@@ -0,0 +1,33 @@
+/**
+ * 数据中台通用接口文档
+ */
+import httputils from "@/api/httputils";
+const baseApi = "/datacenter";
+
+// 查询建筑信息
+export function buildingQuery(postParams: any): any {
+    return httputils.postJson(`${baseApi}/object/building/query`, postParams);
+}
+
+// 字典查询
+export function dictCategoryQuery(postParams: any): any {
+    return httputils.postJson(`${baseApi}/dict/category`, postParams);
+}
+
+// 查询项目下类型的信息点-->编辑器 空间功能类型 列表-->自己转成树
+export function dictQuery(postParams: any): any {
+    // postParams:{
+    // "filters": "code='roomFuncType'",
+    // "type": "GeneralZone"
+    // }
+    return httputils.postJson(`${baseApi}/dict/query`, postParams);
+}
+
+// 查询空间实例
+export function PartiInstancQuery(postParams: any): any {
+    // postParams:{
+    // "filters": "code='roomFuncType'",
+    // "type": "GeneralZone"
+    // }
+    return httputils.postJson(`${baseApi}/object/zone/query`, postParams);
+}

+ 169 - 0
src/api/httputils.ts

@@ -0,0 +1,169 @@
+import axios from "axios";
+import { UserModule } from "@/store/modules/user";
+import { MessageBox } from "element-ui";
+
+const CancelToken = axios.CancelToken;
+let cancel;
+
+// 创建axios实例
+const axiosservice = axios.create({
+    timeout: 30000, // 请求超时时间
+    // @ts-ignore
+    retry: 4, //重新请求次数
+    retryDelay: 1000, //重新请求的间隔
+    credentials: true, // 接口每次请求会跨域携带cookie
+    cancelToken: new CancelToken(function executor(c) {
+        // executor 函数接收一个 cancel 函数作为参数
+        cancel = c;
+    }),
+});
+
+axiosservice.interceptors.request.use(
+    (config) => {
+        config.withCredentials = true; // 允许携带token ,这个是解决跨域产生的相关问题
+        config.headers = {
+            projectId: UserModule.projectId, // 'Pj1101050029',//项目id
+            // "X-Access-Token": UserModule.token, // token
+        };
+        return config;
+    },
+    (error) => {
+        return Promise.reject(error);
+    }
+);
+
+axiosservice.interceptors.response.use(
+    function(res) {
+        //在这里对返回的数据进行处理
+        //console.log('axios interceptors res = ', res.status, res)
+        const resp = res.data;
+        if (resp.result === "unauthc") {
+            MessageBox.confirm("未登陆或登陆信息已失效, 是否重新登陆?", "提示", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "error",
+            })
+                .then((resp) => {
+                    //console.log('--------------------------- confirm', resp)
+                    //router.push('/login')
+                    window.location.reload();
+                })
+                .catch((error) => {
+                    //console.log('--------------------------- cancel', error)
+                    console.log("");
+                });
+        } else if (resp.result == "unauthorization") {
+            MessageBox.alert("无权操作", { title: "警告", type: "error" });
+        }
+        //console.log('axios interceptors resp2 = ', resp.success, resp.errorCode, resp.errorMessage, res)
+        return res;
+    },
+    function(err) {
+        //Do something with response error
+        console.log("axios interceptors err = ", err);
+        return Promise.reject(err);
+    }
+);
+
+/* 下载方法 */
+function downFile(blob: any, fileName: string) {
+    // 非IE下载
+    if ("download" in document.createElement("a")) {
+        const link = document.createElement("a");
+        link.href = window.URL.createObjectURL(blob); // 创建下载的链接
+        link.download = fileName; // 下载后文件名
+        link.style.display = "none";
+        document.body.appendChild(link);
+        link.click(); // 点击下载
+        window.URL.revokeObjectURL(link.href); // 释放掉blob对象
+        document.body.removeChild(link); // 下载完成移除元素
+    } else {
+        // IE10+下载
+        window.navigator.msSaveBlob(blob, fileName);
+    }
+}
+
+export default {
+    async getJson(url: string, params: any) {
+        try {
+            const response = await axiosservice({
+                url,
+                params,
+                method: "get",
+            });
+            return response.data;
+        } catch (err) {
+            throw err;
+        }
+    },
+    async postJson(url: string, data: any) {
+        try {
+            const response = await axiosservice({
+                url,
+                data,
+                method: "post",
+            });
+            return response.data;
+        } catch (err) {
+            throw err;
+        }
+    },
+    async fetchJson(url: string, params: any, data: any) {
+        try {
+            const response = await axiosservice({
+                url,
+                params,
+                data,
+                method: "post",
+            });
+            return response;
+        } catch (err) {
+            throw err;
+        }
+    },
+    async postupload(url: string, data: any) {
+        try {
+            const response = await axiosservice({
+                url,
+                data,
+                method: "post",
+                headers: {
+                    "Content-Type": "multipart/form-data",
+                },
+            });
+            return response.data;
+        } catch (err) {
+            throw err;
+        }
+    },
+    download(url: string, requestData: any) {
+        // 响应类型:arraybuffer, blob
+        axiosservice
+            .post(url, requestData, { responseType: "blob" })
+            .then((resp) => {
+                const headers = resp.headers;
+                const contentType = headers["content-type"];
+
+                console.log("响应头信息", headers);
+                if (!resp.data) {
+                    console.error("响应异常:", resp);
+                    return false;
+                } else {
+                    console.log("下载文件:", resp);
+                    const blob = new Blob([resp.data], { type: contentType });
+
+                    const contentDisposition = resp.headers["content-disposition"];
+                    let fileName = "unknown";
+                    if (contentDisposition) {
+                        fileName = window.decodeURI(resp.headers["content-disposition"].split("=")[1]);
+                    }
+                    console.log("文件名称:", fileName);
+                    downFile(blob, fileName);
+                }
+            })
+            .catch(function(error) {
+                console.log(error);
+            });
+    },
+    axios: axiosservice,
+};

+ 15 - 0
src/api/modelapi.ts

@@ -0,0 +1,15 @@
+/**
+ * 数据中台通用接口文档
+ */
+import httputils from "@/api/httputils";
+const baseUrl = "/modelapi";
+
+// 查询模型文件夹
+export function queryModel(postParams: any): any {
+    return httputils.postJson(`${baseUrl}/model-folder/query`, postParams);
+}
+
+// 查询模型文件夹下的所有模型文件
+export function queryFloorList(postParams: any): any {
+    return httputils.postJson(`${baseUrl}/model-floor/query-list`, postParams);
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 104 - 0
src/icons/svg/暂无内容.svg


+ 5 - 1
src/layout/components/Navbar/index.vue

@@ -6,7 +6,7 @@
         <div class="right-menu">
             <el-dropdown class="avatar-container right-menu-item hover-effect">
                 <div class="avatar-wrapper">
-                    <span> yanruolan </span>
+                    <span> {{username}} </span>
                     <i class="el-icon-user-solid" />
                 </div>
                 <el-dropdown-menu slot="dropdown">
@@ -46,6 +46,10 @@ export default class extends Vue {
         return UserModule.avatar;
     }
 
+    get username() {
+        return UserModule.username;
+    }
+
     private toggleSideBar() {
         AppModule.ToggleSideBar(false);
     }

+ 1 - 0
src/layout/index.vue

@@ -67,6 +67,7 @@ export default class extends mixins(ResizeMixin) {
     margin-left: $sideBarWidth;
     position: relative;
     overflow-y: hidden;
+    padding: 0 10px 10px;
 }
 
 .sidebar-container {

+ 48 - 48
src/store/modules/app.ts

@@ -1,72 +1,72 @@
 import {
-  VuexModule,
-  Module,
-  Mutation,
-  Action,
-  getModule
+    VuexModule,
+    Module,
+    Mutation,
+    Action,
+    getModule
 } from "vuex-module-decorators";
 import { getSidebarStatus, setSidebarStatus } from "@/utils/cookies";
 import store from "@/store";
 
 export enum DeviceType {
-  Mobile,
-  Desktop
+    Mobile,
+    Desktop
 }
 
 export interface IAppState {
-  device: DeviceType;
-  sidebar: {
-    opened: boolean;
-    withoutAnimation: boolean;
-  };
+    device: DeviceType;
+    sidebar: {
+        opened: boolean;
+        withoutAnimation: boolean;
+    };
 }
 
 @Module({ dynamic: true, store, name: "app" })
 class App extends VuexModule implements IAppState {
-  public sidebar = {
-    opened: getSidebarStatus() !== "closed",
-    withoutAnimation: false
-  };
+    public sidebar = {
+        opened: getSidebarStatus() !== "closed",
+        withoutAnimation: false
+    };
 
-  public device = DeviceType.Desktop;
+    public device = DeviceType.Desktop;
 
-  @Mutation
-  private TOGGLE_SIDEBAR(withoutAnimation: boolean) {
-    this.sidebar.opened = !this.sidebar.opened;
-    this.sidebar.withoutAnimation = withoutAnimation;
-    if (this.sidebar.opened) {
-      setSidebarStatus("opened");
-    } else {
-      setSidebarStatus("closed");
+    @Mutation
+    private TOGGLE_SIDEBAR(withoutAnimation: boolean) {
+        this.sidebar.opened = !this.sidebar.opened;
+        this.sidebar.withoutAnimation = withoutAnimation;
+        if (this.sidebar.opened) {
+            setSidebarStatus("opened");
+        } else {
+            setSidebarStatus("closed");
+        }
     }
-  }
 
-  @Mutation
-  private CLOSE_SIDEBAR(withoutAnimation: boolean) {
-    this.sidebar.opened = false;
-    this.sidebar.withoutAnimation = withoutAnimation;
-    setSidebarStatus("closed");
-  }
+    @Mutation
+    private CLOSE_SIDEBAR(withoutAnimation: boolean) {
+        this.sidebar.opened = false;
+        this.sidebar.withoutAnimation = withoutAnimation;
+        setSidebarStatus("closed");
+    }
 
-  @Mutation
-  private TOGGLE_DEVICE(device: DeviceType) {
-    this.device = device;
-  }
+    @Mutation
+    private TOGGLE_DEVICE(device: DeviceType) {
+        this.device = device;
+    }
 
-  @Action
-  public ToggleSideBar(withoutAnimation: boolean) {
-    this.TOGGLE_SIDEBAR(withoutAnimation);
-  }
+    @Action
+    public ToggleSideBar(withoutAnimation: boolean) {
+        this.TOGGLE_SIDEBAR(withoutAnimation);
+    }
 
-  @Action
-  public CloseSideBar(withoutAnimation: boolean) {
-    this.CLOSE_SIDEBAR(withoutAnimation);
-  }
+    @Action
+    public CloseSideBar(withoutAnimation: boolean) {
+        this.CLOSE_SIDEBAR(withoutAnimation);
+    }
 
-  @Action
-  public ToggleDevice(device: DeviceType) {
-    this.TOGGLE_DEVICE(device);
-  }
+    @Action
+    public ToggleDevice(device: DeviceType) {
+        this.TOGGLE_DEVICE(device);
+    }
 }
 
 export const AppModule = getModule(App);

+ 88 - 77
src/store/modules/user.ts

@@ -1,103 +1,114 @@
 import {
-  VuexModule,
-  Module,
-  Action,
-  Mutation,
-  getModule
+    VuexModule,
+    Module,
+    Action,
+    Mutation,
+    getModule
 } from "vuex-module-decorators";
 import { login, logout, getUserInfo } from "@/api/users";
 import { getToken, setToken, removeToken } from "@/utils/cookies";
 import store from "@/store";
 
 export interface IUserState {
-  token: string;
-  name: string;
-  avatar: string;
-  introduction: string;
-  roles: string[];
+    token: string;
+    name: string;
+    username: string;
+    userId: string;
+    projectId: string;
+    avatar: string;
+    introduction: string;
+    roles: string[];
 }
 
 @Module({ dynamic: true, store, name: "user" })
 class User extends VuexModule implements IUserState {
-  public token = getToken() || "";
-  public name = "";
-  public avatar = "";
-  public introduction = "";
-  public roles: string[] = [];
+    public token = getToken() || "";
+    public name = "";
+    public username = "yanruolan";
+    public userId = "06328a53c69a41bb8f5bb1a552c6e8d6";
+    public projectId = "Pj4403070003";// 深圳龙岗万达广场
+    public avatar = "";
+    public introduction = "";
+    public roles: string[] = [];
 
-  @Mutation
-  private SET_TOKEN(token: string) {
-    this.token = token;
-  }
-
-  @Mutation
-  private SET_NAME(name: string) {
-    this.name = name;
-  }
+    @Mutation
+    private SET_TOKEN(token: string) {
+        this.token = token;
+    }
 
-  @Mutation
-  private SET_AVATAR(avatar: string) {
-    this.avatar = avatar;
-  }
+    @Mutation
+    private SET_NAME(name: string) {
+        this.name = name;
+    }
 
-  @Mutation
-  private SET_INTRODUCTION(introduction: string) {
-    this.introduction = introduction;
-  }
+    @Mutation
+    private SET_PROJECTID(projectId: string) {
+        this.projectId = projectId;
+    }
 
-  @Mutation
-  private SET_ROLES(roles: string[]) {
-    this.roles = roles;
-  }
+    @Mutation
+    private SET_AVATAR(avatar: string) {
+        this.avatar = avatar;
+    }
 
-  @Action
-  public async Login(userInfo: { username: string; password: string }) {
-    let { username, password } = userInfo;
-    username = username.trim();
-    const { data } = await login({ username, password });
-    setToken(data.accessToken);
-    this.SET_TOKEN(data.accessToken);
-  }
+    @Mutation
+    private SET_INTRODUCTION(introduction: string) {
+        this.introduction = introduction;
+    }
 
-  @Action
-  public ResetToken() {
-    removeToken();
-    this.SET_TOKEN("");
-    this.SET_ROLES([]);
-  }
+    @Mutation
+    private SET_ROLES(roles: string[]) {
+        this.roles = roles;
+    }
 
-  @Action
-  public async GetUserInfo() {
-    if (this.token === "") {
-      throw Error("GetUserInfo: token is undefined!");
+    @Action
+    public async Login(userInfo: { username: string; password: string }) {
+        let { username, password } = userInfo;
+        username = username.trim();
+        const { data } = await login({ username, password });
+        setToken(data.accessToken);
+        this.SET_TOKEN(data.accessToken);
     }
-    const { data } = await getUserInfo({
-      /* Your params here */
-    });
-    if (!data) {
-      throw Error("Verification failed, please Login again.");
+
+    @Action
+    public ResetToken() {
+        removeToken();
+        this.SET_TOKEN("");
+        this.SET_ROLES([]);
     }
-    const { roles, name, avatar, introduction } = data.user;
-    // roles must be a non-empty array
-    if (!roles || roles.length <= 0) {
-      throw Error("GetUserInfo: roles must be a non-null array!");
+
+    @Action
+    public async GetUserInfo() {
+        if (this.token === "") {
+            throw Error("GetUserInfo: token is undefined!");
+        }
+        const { data } = await getUserInfo({
+            /* Your params here */
+        });
+        if (!data) {
+            throw Error("Verification failed, please Login again.");
+        }
+        const { roles, name, avatar, introduction } = data.user;
+        // roles must be a non-empty array
+        if (!roles || roles.length <= 0) {
+            throw Error("GetUserInfo: roles must be a non-null array!");
+        }
+        this.SET_ROLES(roles);
+        this.SET_NAME(name);
+        this.SET_AVATAR(avatar);
+        this.SET_INTRODUCTION(introduction);
     }
-    this.SET_ROLES(roles);
-    this.SET_NAME(name);
-    this.SET_AVATAR(avatar);
-    this.SET_INTRODUCTION(introduction);
-  }
 
-  @Action
-  public async LogOut() {
-    if (this.token === "") {
-      throw Error("LogOut: token is undefined!");
+    @Action
+    public async LogOut() {
+        if (this.token === "") {
+            throw Error("LogOut: token is undefined!");
+        }
+        await logout();
+        removeToken();
+        this.SET_TOKEN("");
+        this.SET_ROLES([]);
     }
-    await logout();
-    removeToken();
-    this.SET_TOKEN("");
-    this.SET_ROLES([]);
-  }
 }
 
 export const UserModule = getModule(User);

+ 19 - 12
src/styles/index.scss

@@ -6,39 +6,46 @@
 /* Global scss */
 
 body {
-  height: 100%;
-  -moz-osx-font-smoothing: grayscale;
-  -webkit-font-smoothing: antialiased;
-  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
+    height: 100%;
+    -moz-osx-font-smoothing: grayscale;
+    -webkit-font-smoothing: antialiased;
+    font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif,"\5FAE\8F6F\96C5\9ED1";
+    font-size: 14px;
 }
 
 
 #app {
-  height: 100%;
+    height: 100%;
 }
 
 *,
 *:before,
 *:after {
-  box-sizing: border-box;
+    box-sizing: border-box;
+}
+
+ul {
+    list-style-type: none;
+    margin: 0;
+    padding: 0;
 }
 
 a,
 a:focus,
 a:hover {
-  color: inherit;
-  outline: none;
-  text-decoration: none;
+    color: inherit;
+    outline: none;
+    text-decoration: none;
 }
 
 div:focus {
-  outline: none;
+    outline: none;
 }
 
 .clearfix {
-  @include clearfix;
+    @include clearfix;
 }
 
 .app-container {
-  padding: 20px;
+    padding: 20px;
 }

+ 2 - 0
src/utils/bus.ts

@@ -0,0 +1,2 @@
+import Vue from "vue";
+export default new Vue();

+ 237 - 0
src/views/manage/build/components/Floortable/index.vue

@@ -0,0 +1,237 @@
+<template>
+    <div class="filterTable-container">
+        <el-table
+            ref="filterTable"
+            :data="tableData"
+            style="width: 100%"
+            size="small"
+            height="100%"
+            :header-cell-style="{ background: '#d9d9d9', color: '#2b2b2b', height: '41px' }"
+        >
+            <el-table-column prop="FloorName" align="center" label="楼层本地名" width="100"></el-table-column>
+            <el-table-column prop="Version" label="版本号" align="center"></el-table-column>
+            <!-- <el-table-column label="版本号">
+                <template slot-scope="scope">
+                    <span style="margin-right: 5px">{{ scope.row.Version }}</span>
+                    <i
+                        v-show="scope.row.Version && scope.row.Status === 4"
+                        class="iconfont icon-warn"
+                        style="cursor: pointer; position: relative; top: 1px"
+                        title="查看版本更新信息"
+                        @click="handleClickVersion(scope.row)"
+                    ></i>
+                </template>
+            </el-table-column> -->
+            <el-table-column prop="AcceptTime" label="时间" width="240" align="center"></el-table-column>
+            <el-table-column prop="UserName" label="上传人"></el-table-column>
+            <el-table-column prop="address" align="center" label="操作" width="240">
+                <template slot-scope="scope">
+                    <div class="operate" v-show="scope.row.Status === 4">
+                        <el-button
+                            title="下载模型"
+                            type="primary"
+                            size="mini"
+                            class="el-icon-download"
+                            @click="downloadModel(scope.row)"
+                        ></el-button>
+                        <el-button
+                            title="替换模型"
+                            type="primary"
+                            size="mini"
+                            class="el-icon-refresh"
+                            @click="replaceModel(scope.row)"
+                        ></el-button>
+                        <el-button
+                            title="查看版本日志"
+                            type="primary"
+                            size="mini"
+                            class="el-icon-bank-card"
+                            @click="queryModelLog(scope.row)"
+                        ></el-button>
+                        <!-- <el-button
+                            title="下载BIMID模型"
+                            type="primary"
+                            size="mini"
+                            class="el-icon-download"
+                            @click="downloadModelBIMID(scope.row)"
+                        ></el-button> -->
+                    </div>
+                    <div :class="['upLoad-loading']" v-show="scope.row.Status !== 4">
+                        <div class="progress">
+                            <el-progress
+                                :text-inside="false"
+                                :stroke-width="20"
+                                :percentage="100"
+                                :color="scope.row.Status ? '#909399' : '#67C23A'"
+                            ></el-progress>
+                        </div>
+                        <div class="progress-right">
+                            <span v-if="!scope.row.Status">上传中...</span>
+                            <span v-else-if="scope.row.Status === 1">等待检查...</span>
+                            <span v-else>模型检查中...</span>
+
+                            <!-- <span v-show="!scope.row.Status">上传中...</span>
+                            <span v-show="scope.row.Status == 1">等待检查...</span>
+                            <span v-show="scope.row.Status == 10">模型检查中...</span>
+                            <span v-show="scope.row.Status == 11">未通过检查</span>
+                            <span v-show="scope.row.Status == 2 || scope.row.Status == 20">等待数据导出...</span>
+                            <span v-show="scope.row.Status == 21">模型数据导出失败</span>
+                            <span v-show="scope.row.Status == 3">处理导出数据中...</span>
+                            <span v-show="scope.row.Status == 31">同步到数据中心失败</span> -->
+                        </div>
+                    </div>
+                </template>
+            </el-table-column>
+        </el-table>
+        <!-- <version-dialog :dialogVisible.sync="dialogVisible" :modelFile="modelFile" ref="addSpaceDialog"></version-dialog> -->
+    </div>
+</template>
+<script lang="ts">
+import { Vue, Component, Prop, Watch, Emit, Ref } from "vue-property-decorator";
+import { UserModule } from "@/store/modules/user";
+import { ElTable } from "element-ui/types/table";
+// import versionDialog from "@/components/model/file/versionDialog";
+@Component({
+    name: "FloorTable",
+    components: {},
+})
+export default class extends Vue {
+    @Prop({ default: [] }) private tableData!: any[];
+    @Prop({ default: "" }) private modelFolderName!: string;
+
+    private maxHeight = 0;
+    private dialogVisible = false;
+    private modelFile = null;
+
+    @Ref("filterTable") readonly filterTable!: ElTable;
+
+    get projectId() {
+        return UserModule.projectId;
+    }
+
+    get username() {
+        return UserModule.username;
+    }
+
+    // 查看日志
+    @Emit("openModelLog")
+    private queryModelLog(item: any) {
+        return item;
+    }
+
+    // 查看版本信息
+    // private handleClickVersion(item: any) {
+    //     this.modelFile = item;
+    //     this.dialogVisible = true;
+    // }
+
+    // 替换模型
+    private replaceModel(item: any) {
+        if (item.Status !== 4) {
+            this.$alert("正在识别模型对象,请稍后再替换。", "替换模型", { confirmButtonText: "确定" });
+        } else {
+            this.$emit("replaceModel", item);
+        }
+    }
+
+    // 下载模型文件
+    private downloadModel(item: any) {
+        let url = item.Url.match(/(\/image-service\S*)$/g) ? item.Url.match(/(\/image-service\S*)$/g)[0] : "";
+        if (url) {
+            let a = document.createElement("a");
+            a.href = url;
+            a.download = `${this.modelFolderName}${item.FloorName}模型文件v${item.Version}.rvt`;
+            a.click();
+            document.body.removeChild(a);
+        } else {
+            this.$message({
+                message: "该文件夹下没有资源",
+                type: "error",
+            });
+        }
+    }
+
+    // 下载BIMID模型文件
+    private downloadModelBIMID(item: any) {
+        let url = item.Url.match(/(\/image-service\S*)$/g) ? item.Url.match(/(\/image-service\S*)$/g)[0] : "";
+        if (url) {
+            let a = document.createElement("a");
+            a.href = url;
+            a.download = `${this.projectId}${item.FolderId}${item.FloorName}.rvt`;
+            a.click();
+            document.body.removeChild(a);
+        } else {
+            this.$message({
+                message: "该文件夹下没有资源",
+                type: "error",
+            });
+        }
+    }
+}
+</script>
+<style scoped lang="scss">
+.box-card {
+    height: 100%;
+    .filterTable-container {
+        height: calc(100% - 51px);
+    }
+    .operate {
+        .iconfont {
+            font-size: 12px;
+            padding: 7px 12px;
+        }
+    }
+    .icon-termination {
+        color: #f56c6c;
+        background: #fff;
+        padding: 0;
+        border: 0;
+        font-size: 20px;
+        margin-left: 5px;
+    }
+    .upLoad {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        padding: 4px 0;
+        .progress {
+            // width: 150px;
+            width: 175px;
+            height: 20px;
+        }
+        .progress-right {
+            height: 20px;
+            line-height: 20px;
+        }
+    }
+    .upLoad-loading {
+        position: relative;
+        justify-content: center;
+        .progress {
+            width: 220px;
+            height: 20px;
+        }
+        .progress-right {
+            position: absolute;
+            left: 50%;
+            top: 50%;
+            transform: translate(-50%, -50%);
+            color: #fff;
+        }
+    }
+}
+::v-deep .el-icon-warning {
+    display: none;
+    // color: transparent;
+}
+::v-deep .el-progress__text {
+    display: none;
+}
+::v-deep .upLoad-loading .el-progress-bar {
+    padding-right: 44px;
+    margin-right: -44px;
+}
+::v-deep .el-progress-bar__inner {
+    text-align: center;
+}
+</style>

+ 307 - 5
src/views/manage/build/index.vue

@@ -1,12 +1,314 @@
 <template>
-    <div>建筑</div>
+    <div id="file_moddle_manage" v-loading="loading">
+        <!-- 左边模型文件夹列表 -->
+        <div class="col_left">
+            <div class="grid-content grid-left">
+                <el-card class="box-card" :body-style="{ padding: '0px', height: '100%' }">
+                    <div class="top_hand left_top_hand">
+                        <div class="folder-box">
+                            <el-tooltip class="item" effect="dark" content="新建建筑" placement="top-start">
+                                <el-button icon="el-icon-plus" size="small" @click="addFolder"></el-button>
+                            </el-tooltip>
+                            <el-tooltip class="item" effect="dark" content="删除建筑" placement="top-start">
+                                <el-button icon="el-icon-minus" size="small" @click="removeFolder"></el-button>
+                            </el-tooltip>
+                            <el-tooltip class="item" effect="dark" content="编辑建筑" placement="top-start">
+                                <el-button @click="editFolder" icon="el-icon-edit-outline" size="small"></el-button>
+                            </el-tooltip>
+                        </div>
+                    </div>
+                    <div class="folder-list">
+                        <div class="head">建筑</div>
+                        <ul class="lists">
+                            <el-scrollbar style="height: 100%">
+                                <li
+                                    @click="openFolder(index, item)"
+                                    v-for="(item, index) in navigationModel"
+                                    :key="index"
+                                    :class="[choiceIndex === index + 1 ? 'li-active' : '']"
+                                >
+                                    <i
+                                        :class="[choiceIndex === index + 1 ? 'el-icon-folder-opened' : 'el-icon-folder', 'icon_font']"
+                                        width="40"
+                                        height="40"
+                                    ></i>
+                                    <span :title="item.Name">{{ item.Name }}</span>
+                                </li>
+                            </el-scrollbar>
+                        </ul>
+                    </div>
+                </el-card>
+            </div>
+        </div>
+        <!-- 右边文件表格 -->
+        <div class="col_right">
+            <el-card class="box-card" :body-style="{ padding: '0px', height: '100%' }">
+                <!-- 顶部操作栏 -->
+                <div class="top_hand right_top_hand">
+                    <el-button size="small" @click="addFloorFile">添加楼层模型文件</el-button>
+                    <el-button size="small" @click="queryFloorFile(currentFolderId)">刷新</el-button>
+                </div>
+                <!-- 列表 -->
+                <floor-table
+                    v-loading="tableLoading"
+                    ref="floorTable"
+                    :tableData="tableData"
+                    :modelFolderName="currentFolderName"
+                    @openModelLog="queryModelLog"
+                    @replaceModel="repliaceModel"
+                    @percentFinish="queryFloorFile(currentFolderId)"
+                ></floor-table>
+            </el-card>
+        </div>
+        <!-- 弹窗 开始-->
+
+        <!-- 模型日志弹窗 -->
+        <!-- <modelLog
+            :modelLogVisible="modelLogVisible"
+            :modelFolderName="currentFolderName"
+            @deleteFinish="updataLog"
+            @CloseModelLogDia="modelLogVisible = false"
+            :logData="logData"
+        ></modelLog> -->
+        <!-- 替换模型弹窗 -->
+        <!-- <repliceModel
+            :repliceModelVisible="repliceModelVisible"
+            @closeReplaceModelDia="repliceModelVisible = false"
+            :replaceModelItem="replaceModelItem"
+            @updataModel="updateModelFile"
+        ></repliceModel> -->
+        <!-- 新增楼层 -->
+        <!-- <addFloorDialog
+            :addFloorFileVisible="addFloorFileVisible"
+            :floorList="tableData"
+            :FolderName="currentFolderName"
+            :FolderId="currentFolderId"
+            @closeAddFloorDia="addFloorFileVisible = false"
+            @finishCreateFloor="uploadModelFIle"
+        ></addFloorDialog> -->
+        <!-- 新增文件夹名称 -->
+        <!-- <addFolder
+            :addFolderVisible="addFolderVisible"
+            @closeAddFolderVisible="
+                addFolderVisible = false;
+                folderName = '';
+            "
+            :folderName="folderName"
+            @getfolderModel="queryModel"
+        ></addFolder> -->
+        <!-- 编辑文件夹名字 -->
+        <!-- <changeFolderName
+            :currentFolderId="currentFolderId"
+            :changeFolderNameVisible="changeFolderNameVisible"
+            :folderName="folderName"
+            @finishChangeFolderName="queryModel"
+            @closeChangeFolderVisible="
+                changeFolderNameVisible = false;
+                folderName = '';
+            "
+        ></changeFolderName> -->
+        <!-- 弹窗 结束-->
+    </div>
 </template>
 
-<script>
-export default {
-    name: "index"
+<script lang="ts">
+import { Vue, Component, Watch } from "vue-property-decorator";
+import { UserModule } from "@/store/modules/user";
+import { queryFloorList, queryModel } from "@/api/modelapi";
+import Bus from "@/utils/bus";
+import FloorTable from "./components/Floortable/index.vue"; //右侧list表
+
+@Component({
+    name: "buildFloor",
+    components: {
+        FloorTable,
+    },
+})
+export default class extends Vue {
+    private addFolderVisible = false; // 是否显示新增文件夹弹窗
+    private addFloorFileVisible = false; // 是否显示增加楼层文件弹窗
+    private repliceModelVisible = false; // 是否显示替换楼层模型弹窗
+    private modelLogVisible = false; // 是否显示模型日志弹窗
+    private changeFolderNameVisible = false; // 是否显示编辑文件夹弹窗
+
+    private navigationModel: any[] = []; // 文件夹模型list
+    private choiceIndex = 0; // 当前文件夹index
+    private currentFolderId = ""; // 当前选择的文件夹id
+    private currentFolderName = ""; // 当前选择文件夹的Name
+    private tableData = []; // 楼层列表
+    private loading = false; // 加载loading
+    private tableLoading = false; // 表格加载loading
+
+    get projectId() {
+        return UserModule.projectId;
+    }
+
+    mounted() {
+        this.queryModel();
+        Bus.$on("modelStatusChange", () => {
+            this.queryFloorFile(this.currentFolderId);
+        });
+    }
+
+    // 打开模型文件夹
+    private openFolder(index: number, item: any) {
+        this.choiceIndex = index + 1;
+        this.currentFolderId = item.Id;
+        this.currentFolderName = item.Name;
+        // 获取模型文件夹对应得楼层文件
+        this.queryFloorFile(this.currentFolderId);
+    }
+
+    // 查询所有文件夹模型
+    private async queryModel() {
+        this.navigationModel = [];
+        this.loading = true;
+        const res = await queryModel({ Orders: "Name asc" });
+        this.navigationModel = res.Content;
+        this.loading = false;
+        if (this.navigationModel.length) {
+            //默认选择第一个文件夹
+            this.choiceIndex = 1;
+            this.currentFolderName = this.navigationModel[0].Name;
+            this.currentFolderId = this.navigationModel[0].Id;
+            this.queryFloorFile(this.currentFolderId);
+        } else {
+            this.tableData = [];
+        }
+    }
+
+    /**
+     * @info: 状态显示说明
+     * 0: 上传中(上传的用户可操作:中止)
+     * 1: 等待检查
+     * 10: 模型检查中
+     * 11: 未通过检查
+     * 2、20、21、3、31: 正常(所有用户可操作:下载、查看历史)
+     * 4: 正常(所有用户可操作:下载、替换、查看历史)
+     */
+    private async queryFloorFile(currentFolderId: string) {
+        if (currentFolderId) {
+            this.tableData = [];
+            this.tableLoading = true;
+            let params = {
+                Filters: `FolderId='${currentFolderId}'`,
+                PageNumber: 1,
+                PageSize: 1000,
+            };
+            const res = await queryFloorList(params);
+            this.tableData = res.Content;
+            this.tableLoading = false;
+        }
+    }
+
+    private queryModelLog(item: any) {
+        console.log(item);
+    }
+
+    private repliaceModel(item: any) {
+        console.log(item);
+    }
 }
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
+#file_moddle_manage {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    overflow: hidden !important;
+    .col_left {
+        width: 280px;
+        height: 100%;
+    }
+    .col_right {
+        width: calc(100% - 280px);
+        height: 100%;
+    }
+    .grid-content {
+        height: 100%;
+    }
+    .box-card {
+        height: 100%;
+    }
+    .grid-left {
+        padding-right: 10px;
+        box-sizing: border-box;
+    }
+    // 顶部
+    .top_hand {
+        // height: 60px;
+        width: 100%;
+        padding: 10px;
+        box-sizing: border-box;
+        display: flex;
+    }
+    .left_top_hand {
+        align-items: center;
+        justify-content: space-between;
+        .folder-box {
+            ::v-deep .el-button--small {
+                padding: 8.5px 9px;
+            }
+        }
+    }
+    // 左侧文件夹列表
+    .folder-list {
+        width: 100%;
+        height: calc(100% - 52px);
+        .head {
+            height: 41px;
+            width: 100%;
+            padding-left: 10px;
+            box-sizing: border-box;
+            background: #d9d9d9;
+            color: #2b2b2b;
+            display: flex;
+            justify-content: left;
+            align-items: center;
+            font-weight: bold;
+            span {
+                font-weight: normal;
+                font-size: 12px;
+                color: #606266;
+            }
+        }
+        .lists {
+            width: 100%;
+            margin-top: 10px;
+            height: calc(100% - 51px);
+            overflow-y: auto;
+            li {
+                height: 42px;
+                display: flex;
+                justify-content: left;
+                align-items: center;
+                padding-left: 20px;
+                box-sizing: border-box;
+                color: #555;
+                cursor: pointer;
+                span {
+                    padding-left: 6px;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                    white-space: nowrap;
+                }
+            }
+            li:hover {
+                background-color: #f5f7fa;
+                color: #000;
+            }
+            .li-active {
+                background-color: #f5f7fa;
+                color: #000;
+            }
+        }
+    }
+    .icon_font {
+        font-size: 18px;
+    }
+}
+::v-deep .el-scrollbar__wrap {
+    overflow-x: hidden;
+}
 </style>

+ 56 - 44
vue.config.js

@@ -1,48 +1,60 @@
-const path = require('path')
-const name = 'wanda-adm'
-const devServerPort = 28888
-const stageServerPort = 28889
+const path = require("path");
+const name = "wanda-adm";
+const devServerPort = 28888;
+const stageServerPort = 28889;
 module.exports = {
-  // TODO: Remember to change publicPath to fit your need
-  publicPath: process.env.NODE_ENV === 'production' ? '/wanda-adm/' : '/',
-  lintOnSave: process.env.NODE_ENV === 'development',
-  productionSourceMap: false,
-  devServer: {
-    port: devServerPort,
-    open: true,
-    overlay: {
-      warning: false,
-      errors: true
-    },
-    progress: false,
-    proxy: {
-      [process.env.VUE_APP_BASE_API]: {
-        target: `http://127.0.0.1:${stageServerPort}/mock-api/v1`,
-        changeOrigin: true, // needed for virtual hosted sites
-        ws: true, // proxy websockets
-        pathRewrite: {
-          ['^' + process.env.VUE_APP_BASE_API]: ''
+    // TODO: Remember to change publicPath to fit your need
+    publicPath: process.env.NODE_ENV === "production" ? "/wanda-adm/" : "/",
+    lintOnSave: process.env.NODE_ENV === "development",
+    productionSourceMap: false,
+    devServer: {
+        port: devServerPort,
+        open: true,
+        overlay: {
+            warning: false,
+            errors: true
+        },
+        progress: false,
+        proxy: {
+            [process.env.VUE_APP_BASE_API]: {
+                target: `http://127.0.0.1:${stageServerPort}/mock-api/v1`,
+                changeOrigin: true, // needed for virtual hosted sites
+                ws: true, // proxy websockets
+                pathRewrite: {
+                    ["^" + process.env.VUE_APP_BASE_API]: ""
+                }
+            },
+            "/datacenter": {
+                target: "http://60.205.177.43:28888",
+                changeOrigin: true,
+                secure: false
+            },
+            "/modelapi": {
+                target: "http://39.102.40.239:8080/",
+                changeOrigin: true,
+                pathRewrite: {
+                    "^/modelapi": "/revit-algorithm"
+                }
+            }
         }
-      }
-    }
-  },
+    },
 
-  pluginOptions: {
-    'style-resources-loader': {
-      preProcessor: 'scss',
-      patterns: [
-        path.resolve(__dirname, 'src/styles/_variables.scss'),
-        path.resolve(__dirname, 'src/styles/_mixins.scss')
-      ]
+    pluginOptions: {
+        "style-resources-loader": {
+            preProcessor: "scss",
+            patterns: [
+                path.resolve(__dirname, "src/styles/_variables.scss"),
+                path.resolve(__dirname, "src/styles/_mixins.scss")
+            ]
+        }
+    },
+    chainWebpack(config) {
+        // provide the app's title in html-webpack-plugin's options list so that
+        // it can be accessed in index.html to inject the correct title.
+        // https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-plugin
+        config.plugin("html").tap(args => {
+            args[0].title = name;
+            return args;
+        });
     }
-  },
-  chainWebpack(config) {
-    // provide the app's title in html-webpack-plugin's options list so that
-    // it can be accessed in index.html to inject the correct title.
-    // https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-plugin
-    config.plugin('html').tap(args => {
-      args[0].title = name
-      return args
-    })
-  }
-}
+};