Kaynağa Gözat

feature:(技术服务)增加技术服务模块和中心平台模块

liuzhenlin 1 yıl önce
ebeveyn
işleme
c3dee08312

+ 144 - 142
src/App.vue

@@ -6,27 +6,29 @@
           <div class="logo mr12">
             <img src="./assets/img/common-logo.png" alt />
           </div>
-          <el-menu :default-active="defaultActive"
-                   class="el-menu-demo"
-                   mode="horizontal"
-                   menu-trigger="hover"
-                   @select="handleSelect"
-                   :router="router">
+          <el-menu
+            :default-active="defaultActive"
+            class="el-menu-demo"
+            mode="horizontal"
+            menu-trigger="hover"
+            @select="handleSelect"
+            :router="router"
+          >
             <el-menu-item index="/">首页</el-menu-item>
             <el-menu-item index="/introduce">中心介绍</el-menu-item>
             <el-menu-item index="/news">新闻动态</el-menu-item>
             <el-submenu index="/appointment" popper-class="custom-submenu">
-              <template slot="title">
-                预约管理
-              </template>
+              <template slot="title">预约管理</template>
               <el-menu-item index="/appointment/equipment">
                 仪器设备
               </el-menu-item>
               <el-menu-item index="/appointment/equipment-details" v-if="false">
                 仪器设备详情
               </el-menu-item>
-              <el-menu-item index="2-2">中心平台</el-menu-item>
-              <el-menu-item index="2-3">技术服务</el-menu-item>
+              <el-menu-item index="/technical-plat/index">中心平台</el-menu-item>
+              <el-menu-item index="/technical/service">
+                技术服务
+              </el-menu-item>
             </el-submenu>
             <el-menu-item index="/product">教育培训</el-menu-item>
             <el-menu-item index="/case">资料下载</el-menu-item>
@@ -50,7 +52,7 @@
             <el-dropdown class="ml12" size="medium" @command="handleCommand">
               <span class="flex flex-center">
                 <img v-if="userInfo.avatar" :src="userInfo.avatar" />
-                <img v-else src="./assets/img/default-avatar.png">
+                <img v-else src="./assets/img/default-avatar.png" />
                 <i class="el-icon-arrow-down el-icon--right"></i>
               </span>
               <el-dropdown-menu slot="dropdown">
@@ -71,150 +73,150 @@
 </template>
 
 <script>
-import { mapGetters } from "vuex";
-export default {
-  computed: {
-    ...mapGetters(["userInfo"]),
-  },
-  watch: {
-    $route: {
-      handler(val) {
-        this.defaultActive = val.path;
-      },
-      immediate: true,
-    },
-  },
-  data() {
-    return {
-      router: true,
-      defaultActive: "/",
-      isShow: false,
-    };
-  },
-  methods: {
-    handleSelect(key) {
-      this.isShow = this.defaultActive != key;
-      window.console.log(this.isShow);
+  import { mapGetters } from "vuex";
+  export default {
+    computed: {
+      ...mapGetters(["userInfo"]),
     },
-    onRegister() {
-      this.$router.push("/register");
+    watch: {
+      $route: {
+        handler(val) {
+          this.defaultActive = val.path;
+        },
+        immediate: true,
+      },
     },
-    toLogin() {
-      this.$router.push("/login");
+    data() {
+      return {
+        router: true,
+        defaultActive: "/",
+        isShow: false,
+      };
     },
-    toCenter() {
-      this.$router.push("/personal-center/work");
+    methods: {
+      handleSelect(key) {
+        this.isShow = this.defaultActive != key;
+        window.console.log(this.isShow);
+      },
+      onRegister() {
+        this.$router.push("/register");
+      },
+      toLogin() {
+        this.$router.push("/login");
+      },
+      toCenter() {
+        this.$router.push("/personal-center/work");
+      },
+      handleCommand(command) {
+        if (command == "logOut") {
+          this.$confirm("确定注销吗?", "提示", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+          }).then(() => {
+            this.$store.dispatch("logOut").then(() => this.$router.push("/"));
+          });
+        }
+      },
     },
-    handleCommand(command) {
-      if (command == "logOut") {
-        this.$confirm("确定注销吗?", "提示", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(() => {
-          this.$store.dispatch('logOut').then(() => this.$router.push('/'))
-        })
-      }
-    }
-  },
-};
+  };
 </script>
 
 <style lang="scss">
-* {
-  padding: 0;
-  margin: 0;
-}
-html,
-body {
-  height: 100%;
-}
-
-#app {
-  font-family: "Avenir", Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  color: #2c3e50;
-}
-
-.el-header {
-  display: flex;
-  justify-content: space-between;
-  align-content: center;
-  align-items: center;
-  width: 100%;
-  margin: 0 auto;
-  height: 84px !important;
-  .flex {
-    height: 100%;
-  }
-  .el-menu-demo {
-    flex: 1;
-    overflow-x: auto;
-    overflow-y: hidden;
-  }
-  .el-menu-item.is-active {
-    border-bottom: 2px solid #409eff !important;
-  }
-  .el-menu,
-  .el-submenu,
-  .el-submenu__title,
-  .el-menu-item {
-    height: 40px !important;
-    line-height: 40px !important;
-    font-weight: bold;
-    i {
-      display: none;
-    }
-  }
-  .el-menu.el-menu--horizontal,
-  .el-menu-demo .el-menu-item,
-  .el-submenu .el-submenu__title {
-    border-bottom: none;
-    font-weight: bold;
-    font-size: 18px;
-    color: #323232;
+  * {
     padding: 0;
-    margin: 0 20px;
+    margin: 0;
   }
-  .el-menu.el-menu--horizontal,
-  .el-submenu .el-submenu__title {
-    font-weight: bold;
-    font-size: 18px;
-    color: #323232 !important;
+  html,
+  body {
+    height: 100%;
   }
-  .logo {
-    height: 84px;
-    padding: 10px;
-    img {
-      width: 100%;
-      line-height: 60px;
-    }
+
+  #app {
+    font-family: "Avenir", Helvetica, Arial, sans-serif;
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+    color: #2c3e50;
   }
-  .user {
+
+  .el-header {
     display: flex;
+    justify-content: space-between;
+    align-content: center;
     align-items: center;
-    img {
-      width: 36px;
-      height: 36px;
-      border-radius: 50%;
+    width: 100%;
+    margin: 0 auto;
+    height: 84px !important;
+    .flex {
+      height: 100%;
+    }
+    .el-menu-demo {
+      flex: 1;
+      overflow-x: auto;
+      overflow-y: hidden;
+    }
+    .el-menu-item.is-active {
+      border-bottom: 2px solid #409eff !important;
+    }
+    .el-menu,
+    .el-submenu,
+    .el-submenu__title,
+    .el-menu-item {
+      height: 40px !important;
+      line-height: 40px !important;
+      font-weight: bold;
+      i {
+        display: none;
+      }
+    }
+    .el-menu.el-menu--horizontal,
+    .el-menu-demo .el-menu-item,
+    .el-submenu .el-submenu__title {
+      border-bottom: none;
+      font-weight: bold;
+      font-size: 18px;
+      color: #323232;
+      padding: 0;
+      margin: 0 20px;
+    }
+    .el-menu.el-menu--horizontal,
+    .el-submenu .el-submenu__title {
+      font-weight: bold;
+      font-size: 18px;
+      color: #323232 !important;
+    }
+    .logo {
+      height: 84px;
+      padding: 10px;
+      img {
+        width: 100%;
+        line-height: 60px;
+      }
+    }
+    .user {
+      display: flex;
+      align-items: center;
+      img {
+        width: 36px;
+        height: 36px;
+        border-radius: 50%;
+      }
     }
   }
-}
-.el-main {
-  padding: 0 !important;
-}
+  .el-main {
+    padding: 0 !important;
+  }
 
-.footer {
-  width: 100%;
-  height: 32px;
-  overflow: hidden;
-  background-color: #386afe;
-  font-weight: 400;
-  font-size: 14px;
-  color: #ffffff;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-}
+  .footer {
+    width: 100%;
+    height: 32px;
+    overflow: hidden;
+    background-color: #386afe;
+    font-weight: 400;
+    font-size: 14px;
+    color: #ffffff;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
 </style>

BIN
src/assets/img/plat.png


BIN
src/assets/img/service.png


+ 27 - 4
src/assets/styles/index.scss

@@ -104,6 +104,7 @@ body,
   position: relative;
   overflow: visible;
   font-weight: bold;
+
   &::before {
     content: '';
     display: block;
@@ -117,6 +118,7 @@ body,
     border-style: solid;
     border-color: transparent transparent #fff transparent;
   }
+
   .el-menu {
     padding: 8px;
     border-radius: 4px;
@@ -131,26 +133,37 @@ body,
     line-height: 24px;
     text-align: left;
     border-radius: 2px;
+
     &:hover {
       background-color: #ebf3ff !important;
       color: #386afe !important;
     }
+
     &.is-active {
       background-color: #ebf3ff !important;
       color: #386afe !important;
     }
+
     &:nth-child(1) {
-      &:hover, &.is-active {
+
+      &:hover,
+      &.is-active {
         background: url('../img/sub-menu-1.png') right no-repeat;
       }
     }
+
     &:nth-child(2) {
-      &:hover, &.is-active {
+
+      &:hover,
+      &.is-active {
         background: url('../img/sub-menu-2.png') right no-repeat;
       }
     }
+
     &:nth-child(3) {
-      &:hover, &.is-active {
+
+      &:hover,
+      &.is-active {
         background: url('../img/sub-menu-3.png') right no-repeat;
       }
     }
@@ -193,6 +206,7 @@ body,
   margin-right: 24px;
   display: flex;
   flex-direction: column;
+
   h4 {
     height: 72px;
     line-height: 72px;
@@ -206,6 +220,7 @@ body,
   ul {
     flex: 1;
     margin-bottom: 10px;
+
     li {
       height: 60px;
       font-weight: 400;
@@ -255,6 +270,7 @@ body,
     align-items: center;
     justify-content: space-between;
     height: 24px;
+
     h4 {
       font-weight: bold;
       font-size: 18px;
@@ -283,15 +299,18 @@ body,
     }
   }
 
-  
+
 }
+
 .link-list {
   display: flex;
   flex-direction: column;
   height: 100%;
   overflow-y: auto;
+
   >ul {
     flex: 1;
+
     li {
       display: flex;
       justify-content: space-between;
@@ -299,9 +318,11 @@ body,
       border-bottom: 1px dashed #ebf1f6;
       cursor: pointer;
       transition: all 0.3s;
+
       &:hover {
         background-color: #e7f1ff;
       }
+
       div {
         font-weight: 400;
         font-size: 16px;
@@ -311,6 +332,7 @@ body,
         overflow: hidden;
         text-overflow: ellipsis;
       }
+
       span {
         font-weight: 400;
         font-size: 16px;
@@ -326,6 +348,7 @@ body,
     justify-content: center;
   }
 }
+
 .def-tabs-wrap {
   .el-tabs__nav-scroll {
     background: #f3f6fb;

+ 26 - 10
src/router.js

@@ -45,6 +45,18 @@ let router = new Router({
         },
       ],
     },
+    // 技术服务
+    {
+      path: "/technical/service",
+      name: "service",
+      component: () => import("./views/technical/service.vue"),
+    },
+    // 中心平台
+    {
+      path: "/technical-plat/index",
+      name: "technical-plat",
+      component: () => import("./views/technical-plat/index.vue"),
+    },
     {
       path: "/product",
       name: "product",
@@ -71,9 +83,9 @@ let router = new Router({
       component: () => import("./views/Register.vue"),
     },
     {
-      path: '/login',
-      name: 'login',
-      component: () => import('./views/Login.vue')
+      path: "/login",
+      name: "login",
+      component: () => import("./views/Login.vue"),
     },
     {
       path: "/personal-center",
@@ -98,14 +110,14 @@ let router = new Router({
             requireAuth: true,
           },
           component: () => import("./views/PersonalCenter/appointment.vue"),
-        }
-      ]
+        },
+      ],
     },
     {
       path: "/contact-us",
       name: "contactUs",
       component: () => import("./views/ContactUs.vue"),
-    }
+    },
   ],
 });
 
@@ -116,9 +128,13 @@ router.beforeEach(async (to, from, next) => {
   if (token && !store.getters.userInfo.id) {
     const [err, res] = await awaitTo(getUserByUserName());
     if (err) return;
-    const obj = res.data.userInfo
-    obj.roleNames = res.data.roles ? res.data.roles.map(item => item.roleName).join(',') : ''
-    obj.pgName = res.data.projectGroupRes ? res.data.projectGroupRes.pgName : ''
+    const obj = res.data.userInfo;
+    obj.roleNames = res.data.roles
+      ? res.data.roles.map((item) => item.roleName).join(",")
+      : "";
+    obj.pgName = res.data.projectGroupRes
+      ? res.data.projectGroupRes.pgName
+      : "";
     store.dispatch("setUserInfo", obj);
   }
   // 判断是否需要登录权限
@@ -126,7 +142,7 @@ router.beforeEach(async (to, from, next) => {
     // 判断是否登录
     if (token) {
       next();
-    } else if(to.path != '/login'){
+    } else if (to.path != "/login") {
       // 没登录则跳转到登录界面
       next({
         path: "/login",

+ 505 - 0
src/views/technical-plat/index.vue

@@ -0,0 +1,505 @@
+<template>
+  <div class="instr-container">
+    <div class="search-wrap"></div>
+    <div class="common-container">
+      <section class="section-container">
+        <div class="filter-wrap">
+          <div class="filter-item dept-wrap">
+            <!-- 实验室管理的实验室 -->
+            <div class="left-tit">技术平台</div>
+            <div class="right-filter-content">
+              <div
+                class="more-item"
+                @click="handleExpandFilter()"
+                v-if="laboratoryNameOptions.length > 8"
+              >
+                <span>{{ platFilterExpand ? "收起" : "更多" }}</span>
+                <i v-if="!platFilterExpand" class="el-icon-caret-top"></i>
+                <i v-else class="el-icon-caret-bottom"></i>
+              </div>
+              <div class="list">
+                <div
+                  @click="selectFilterItem(v)"
+                  class="name"
+                  :class="{ avtive: searchForm.laboratoryName == v.name }"
+                  v-for="(v, i) in laboratoryNameOptions"
+                  v-show="!platFilterExpand ? i < 8 : i > -1"
+                  :key="i"
+                >
+                  {{ `${v}` }}
+                </div>
+                <!-- <div class="dragger-container" v-if="platFilterExpand">
+                  <div class="dragger-bar"></div>
+                </div> -->
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="service-list">
+          <div class="service-list-header">
+            <h4 class="title">技术平台</h4>
+          </div>
+          <el-empty
+            v-if="serviceDataList.length == 0"
+            description="很抱歉,没有找到相关的技术平台~"
+          ></el-empty>
+          <div v-else>
+            <div class="instr-item" v-for="v in serviceDataList" :key="v.id">
+              <div class="img-item">
+                <img
+                  src="../../assets/img/plat.png"
+                  style="width: 100%"
+                  alt=""
+                />
+              </div>
+              <div class="text-item">
+                <p class="name mb20">{{ v.name }}</p>
+                <p class="mb20">说明{{ v.content }}</p>
+                <p class="mb20">负责人:{{ v.user }}</p>
+                <p class="mb20">地点:{{ v.place }}</p>
+                <div class="info">
+                  <div class="info-txt">
+                    <div class="btns flex">
+                      <div class="btn btn1">详情</div>
+                      <div class="btn btn2" @click="joinNeedList(v.id)">
+                        预约
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+              <!-- <div class="appoint-item">
+                <div class="mb20">
+                  <el-button
+                    type="primary"
+                    size="default"
+                    v-if="v.instStatus == '10' && v.isAppointment == '10'"
+                    @click="handleAppoint(v)"
+                  >
+                    使用预约
+                  </el-button>
+                </div>
+                <div>
+                  <el-button
+                    type="primary"
+                    plain
+                    size="default"
+                    @click="linkToDetails(v)"
+                  >
+                    查看详情
+                  </el-button>
+                </div>
+              </div> -->
+            </div>
+          </div>
+          <div class="pagination">
+            <el-pagination
+              background
+              @size-change="handleSizeChange"
+              @current-change="handleCurrentChange"
+              :current-page="searchForm.pageNum"
+              :page-sizes="[10, 50, 100]"
+              :page-size="searchForm.pageSize"
+              layout="total, sizes, prev, pager, next, jumper"
+              :total="total"
+            ></el-pagination>
+          </div>
+        </div>
+      </section>
+    </div>
+  </div>
+</template>
+
+<script name="technical-plat">
+  import to from "await-to-js";
+  import { getToken } from "@/utils/auth";
+  import { Loading } from "element-ui";
+  import { getInstrList, getInstNameEnCount } from "@/api/instr/index";
+  export default {
+    name: "equipment",
+    data() {
+      return {
+        platFilterExpand: false,
+        instrTypeFilterExpand: false,
+        searchForm: {
+          searchText: "",
+          laboratoryName: "",
+          instClassDesc: "",
+          instNameEn: "",
+          pageNum: 1,
+          pageSize: 10,
+        },
+        needList: [],
+        total: 3,
+        serviceDataList: [
+          {
+            id: 1,
+            name: "分子生物平台(全平台)",
+            content:
+              "包含基础实验台、细胞培养和观察设备、细胞分析和操作设备、冷冻冷藏设备、基础试剂等;",
+            place: "遵义医科大学公共实验室7栋6层-细胞平台中心-12室",
+            user: "张老师",
+          },
+          {
+            id: 2,
+            name: "分子生物平台(基础操作设备)",
+            content:
+              "包含基础实验台、细胞培养和观察设备、细胞分析和操作设备、冷冻冷藏设备、基础试剂等;",
+            place: "遵义医科大学公共实验室7栋6层-细胞平台中心-12室",
+            user: "张老师",
+          },
+          {
+            id: 3,
+            name: "分子生物平台(细胞分析设备)",
+            content:
+              "包含基础实验台、细胞培养和观察设备、细胞分析和操作设备、冷冻冷藏设备、基础试剂等;",
+            place: "遵义医科大学公共实验室7栋6层-细胞平台中心-12室",
+            user: "张老师",
+          },
+        ],
+        laboratoryNameOptions: [
+          "细胞平台",
+          "分子生物学平台",
+          "光学平台",
+          "精密仪器平台",
+          "病理平台",
+          "动物平台",
+        ],
+        instClassDescOptions: [],
+        instNameEnOptions: [],
+        options: {
+          text: "正在加载中,请稍后...",
+          background: "rgba(0, 0, 0, 0.6)",
+        },
+      };
+    },
+    created() {},
+
+    mounted() {
+      // this.getInstrData();
+    },
+
+    methods: {
+      joinNeedList(id) {
+        this.needList.push(id);
+        this.needList = [...new Set(this.needList)];
+      },
+      handleAppoint() {
+        this.$refs.appointRef.openDialog();
+        // const token = getToken();
+        // if (!token) {
+        //   return this.$router.push("/login?redirect=/appointment/equipment");
+        // }
+        // this.$refs.appointRef.openDialog(row);
+      },
+      // 获取型号数量
+      async getInstNameEnCountData() {
+        const params = {
+          instClassDesc: this.searchForm.instClassDesc,
+          laboratoryName: this.searchForm.laboratoryName,
+          searchText: this.searchForm.searchText,
+        };
+        const [err, res] = await to(getInstNameEnCount(params));
+        if (err) return;
+        if (res.code == 200) {
+          this.instNameEnOptions = res.data;
+        }
+      },
+      // 上方搜索查询
+      async globalSearch() {
+        this.searchForm.pageNum = 1;
+        this.searchForm.instClassDesc = "";
+        this.searchForm.laboratoryName = "";
+        this.searchForm.instNameEn = "";
+        this.getInstrData();
+      },
+      async getInstrData() {
+        // Loading.service(this.loadingOption);
+        // const [err, res] = await to(getInstrList(this.searchForm));
+        // setTimeout(() => {
+        //   Loading.service(this.loadingOption).close();
+        // });
+        // if (err) return;
+        // if (res.code == 200) {
+        //   this.serviceDataList = res.data.list;
+        //   this.total = res.data.total;
+        //   this.laboratoryNameOptions = this.objTransforArr(
+        //     res.data.count.laboratoryName
+        //   );
+        //   this.instClassDescOptions = this.objTransforArr(
+        //     res.data.count.instClassDesc
+        //   );
+        //   this.getInstNameEnCountData();
+        // }
+      },
+      // 对象转数组
+      objTransforArr(obj) {
+        const arr = Object.entries(obj).map(([key, value]) => ({
+          name: key,
+          count: value,
+        }));
+        return arr;
+      },
+      // 删除查询条件
+      closeTag(type) {
+        switch (type) {
+          case "laboratoryName":
+            this.searchForm.laboratoryName = "";
+            break;
+          case "instClassDesc":
+            this.searchForm.instClassDesc = "";
+            break;
+          case "instNameEn":
+            this.searchForm.instNameEn = "";
+            break;
+        }
+        this.searchForm.pageNum = 1;
+        this.getInstrData();
+      },
+      // 展开 合并
+      handleExpandFilter() {
+        this.platFilterExpand = !this.platFilterExpand;
+      },
+      // 选择查询条件
+      selectFilterItem(name) {
+        this.searchForm.laboratoryName = name;
+      },
+      handleSizeChange(val) {
+        this.searchForm.pageSize = val;
+        this.getInstrData();
+      },
+      handleCurrentChange(val) {
+        this.searchForm.pageNum = val;
+        this.getInstrData();
+      },
+      linkToDetails(v) {
+        this.$router.push("/appointment/equipment-details?id=" + v.id);
+      },
+    },
+  };
+</script>
+
+<style lang="scss" scoped>
+  .search-wrap {
+    width: 100%;
+    height: 240px;
+    position: relative;
+    &::after {
+      display: block;
+      content: "";
+      width: 100%;
+      height: 100%;
+      position: absolute;
+      top: 0;
+      left: 0;
+      background: url("../../assets/img/equipment-banner1.png") center;
+      background-size: 100% 240px;
+    }
+  }
+  .section-container {
+    width: 1200px;
+    margin: 0 auto;
+  }
+  .filter-wrap {
+    width: 100%;
+    .filter-item {
+      width: 100%;
+      min-height: 48px;
+      display: flex;
+      border-bottom: 2px dashed rgba(112, 112, 112, 0.18);
+      &:last-child {
+        border-bottom: none;
+      }
+    }
+
+    .left-tit {
+      width: 120px;
+      background: #f1f1f1;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-weight: bold;
+    }
+    .right-filter-content {
+      flex: 1;
+      padding: 9px 24px 9px 36px;
+      display: flex;
+      flex-wrap: wrap;
+      position: relative;
+      .list {
+        max-height: 120px;
+        overflow: auto;
+        width: 100%;
+        display: flex;
+        flex-wrap: wrap;
+        // &::-webkit-scrollbar {
+        //   display: none;
+        // }
+        .dragger-container {
+          position: absolute;
+          width: 6px;
+          top: 36px;
+          right: 34px;
+          height: 84px;
+          background: #ccc;
+          border-radius: 20px;
+          .dragger-bar {
+            position: absolute;
+            width: 6px;
+            height: 60px;
+            top: 0px;
+            border-radius: 20px;
+            background: rgba(0, 0, 0, 0.75);
+          }
+        }
+      }
+      .name {
+        font-size: 14px;
+        margin: 5px 30px 5px 0;
+        cursor: pointer;
+        &:hover {
+          text-decoration: underline;
+          color: #1677ff;
+        }
+        &.avtive {
+          text-decoration: underline;
+          color: #1677ff;
+        }
+      }
+      .more-item {
+        position: absolute;
+        top: 12px;
+        right: 0;
+        padding-right: 16px;
+        font-size: 14px;
+        cursor: pointer;
+        z-index: 2;
+        i {
+          color: #b1b1b1;
+        }
+      }
+    }
+  }
+  .service-list-header {
+    padding: 15px 18px;
+    display: flex;
+    border: 1px solid rgba(112, 112, 112, 0.06);
+    position: relative;
+    .title {
+      width: 120px;
+      font-size: 16px;
+      color: #333;
+      font-weight: 700;
+      padding-right: 18px;
+      padding-top: 3px;
+      flex: 0 0 120px;
+    }
+    .filter-wrap {
+      min-height: 45px;
+      padding-right: 80px;
+    }
+  }
+  .service-list {
+    background: #fff;
+    border-radius: 6px;
+    margin-top: 20px;
+    min-height: 200px;
+    .list-header {
+      padding: 12px 30px 10px;
+      border-bottom: 1px solid rgba(112, 112, 112, 0.06);
+      align-items: center;
+      justify-content: space-between;
+      .btn {
+        cursor: pointer;
+        background: #facd91;
+        border-top-left-radius: 8px;
+        border-top-right-radius: 8px;
+        padding: 8px 50px;
+      }
+    }
+    .instr-item {
+      padding: 24px 30px;
+      display: flex;
+      border-bottom: 1px solid rgba(112, 112, 112, 0.06);
+      align-items: center;
+      .img-item {
+        width: 100px;
+        height: 100px;
+        border-radius: 6px;
+        overflow: hidden;
+        margin-right: 18px;
+        position: relative;
+        background: #f3f6fb;
+      }
+      .text-item {
+        flex: 1;
+        width: 0;
+        font-size: 14px;
+        padding-top: 6px;
+        display: flex;
+        flex-direction: column;
+        .name {
+          font-weight: bold;
+          font-size: 20px;
+          margin-bottom: 12px;
+        }
+        .info {
+          color: #666;
+          display: flex;
+          font-size: 14px;
+          margin-bottom: 8px;
+          .info-title {
+            width: 100px;
+          }
+          .info-txt {
+            width: 0;
+            flex: 1;
+            position: relative;
+            .btns {
+              position: absolute;
+              right: 0;
+              top: -8px;
+            }
+            .btn {
+              width: 90px;
+              padding: 8px;
+              cursor: pointer;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              &.btn1 {
+                border-top-left-radius: 8px;
+                border-bottom-left-radius: 8px;
+                background: #facd91;
+              }
+              &.btn2 {
+                color: #fff;
+                border-top-right-radius: 8px;
+                border-bottom-right-radius: 8px;
+                background: #1c9bfd;
+              }
+            }
+          }
+        }
+      }
+      .appoint-item {
+        width: 120px;
+        padding: 0 0 0 18px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+  }
+  .pagination {
+    width: 100%;
+    height: 50px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  div {
+    color: #333;
+  }
+</style>

+ 542 - 0
src/views/technical/components/edit.vue

@@ -0,0 +1,542 @@
+<template>
+  <div>
+    <el-dialog
+      :title="title"
+      :visible.sync="state.isShowDialog"
+      :close-on-click-modal="false"
+      width="1200px"
+    >
+      <div class="appoint-section">
+        <el-steps :active="step" simple align-center>
+          <el-step title="第一步:预约信息" icon="el-icon-edit"></el-step>
+          <el-step title="第二步:实验信息" icon="el-icon-goods"></el-step>
+          <el-step title="第三步:费用信息" icon="el-icon-s-finance"></el-step>
+        </el-steps>
+        <div class="r-form mt20" v-show="step == 1">
+          <h3 class="mb14 step-tit">基本信息</h3>
+          <el-form
+            ref="editFormRef"
+            :model="form"
+            label-width="100px"
+            size="mini"
+            label-position="top"
+            :rules="rules"
+            closeable
+          >
+            <div class="form-group">
+              <el-row :gutter="20" class="form-row-wrap">
+                <el-col :span="12">
+                  <el-form-item label="课题名称" prop="userContact">
+                    <div class="flex">
+                      <!-- <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field1"
+                      />
+                      <el-button type="primary">选择</el-button> -->
+                      <el-select
+                        style="width: 100%"
+                        placeholder="请选择"
+                        v-model="form.field1"
+                        value-key=""
+                        clearable
+                        filterable
+                        @change="changeField1"
+                      >
+                        <el-option
+                          label="肿瘤研究课题"
+                          value="肿瘤研究课题"
+                        ></el-option>
+                      </el-select>
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="课题类型" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field2"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="课题来源类型" prop="userContact">
+                    <div class="flex">
+                      <el-select
+                        style="width: 100%"
+                        placeholder="请选择"
+                        v-model="form.field3"
+                        value-key=""
+                        clearable
+                        filterable
+                        @change=""
+                      >
+                        <el-option label="省自然" value="省自然"></el-option>
+                        <el-option label="国自然" value="国自然"></el-option>
+                      </el-select>
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="课题来源名称" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field4"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="课题编号" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field5"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="科室/部门" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field6"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="课题负责人" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field7"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="联系电话" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field8"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="邮箱" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field9"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="科室" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field10"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="实验负责人" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field11"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="工号/学号" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field12"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="联系电话" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field13"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                  <el-form-item label="科室" prop="userContact">
+                    <div class="flex">
+                      <el-input
+                        placeholder="请输入"
+                        class="w100"
+                        maxlength="11"
+                        v-model="form.field14"
+                      />
+                    </div>
+                  </el-form-item>
+                </el-col>
+                <!-- END -->
+              </el-row>
+            </div>
+            <!-- END -->
+          </el-form>
+        </div>
+        <div class="r-form mt20" v-show="step == 2">
+          <div class="plat-tab def-tabs-wrap">
+            <el-tabs v-model="activeName" class="platform-tab">
+              <el-tab-pane label="一、Western Blot" name="10"></el-tab-pane>
+              <el-tab-pane label="二、高效液相色谱实验" name="20"></el-tab-pane>
+              <el-tab-pane
+                label="三、核酸提取扩增相关实验"
+                name="30"
+              ></el-tab-pane>
+              <el-tab-pane
+                label="四、组织与病理学相关实验"
+                name="40"
+              ></el-tab-pane>
+            </el-tabs>
+          </div>
+          <div class="exper-info-list">
+            <form1 v-show="activeName == '10'"></form1>
+            <form2 v-show="activeName == '20'"></form2>
+            <form3 v-show="activeName == '30'"></form3>
+            <form4 v-show="activeName == '40'"></form4>
+          </div>
+        </div>
+        <div class="r-form mt20" v-show="step == 3">
+          <h3 class="mb14 step-tit">费用及支付方式</h3>
+          <p class="mb14">本项技术服务项目费用构成如下:</p>
+          <el-table
+            size="mini"
+            :data="itemList"
+            border
+            stripe
+            show-summary
+            :summary-method="getSummaries"
+          >
+            <el-table-column type="index" label="序号" width="50" />
+            <el-table-column prop="plat" label="服务平台"></el-table-column>
+            <el-table-column prop="proj" label="服务项目"></el-table-column>
+            <el-table-column prop="name" label="服务内容"></el-table-column>
+            <el-table-column prop="price" label="单价"></el-table-column>
+            <el-table-column prop="count" label="数量"></el-table-column>
+            <el-table-column prop="total" label="小计"></el-table-column>
+          </el-table>
+          <p class="mt20 mb14">
+            本次技术服务费总金额为 ¥
+            <el-input
+              size="mini"
+              style="width: 100px"
+              v-model="price1"
+            ></el-input>
+            元(大写
+            <el-input
+              size="mini"
+              style="width: 100px"
+              v-model="price2"
+            ></el-input>
+            圆整);
+          </p>
+          <p class="mb14">支付方式:在实验开始前</p>
+          <div class="mb14">
+            <el-checkbox v-model="checked1">
+              若该项技术服务费用总金额不超过5000元的,在实验开始前一次性付清;
+            </el-checkbox>
+          </div>
+          <div class="flex">
+            <el-checkbox class="mr10" v-model="checked2"></el-checkbox>
+            <div>
+              <div class="mb14">
+                若高于5000元的,须预先支付60%的费用,金额为 ¥
+                <el-input
+                  size="mini"
+                  style="width: 100px"
+                  v-model="price3"
+                ></el-input>
+                元整(大写
+                <el-input
+                  size="mini"
+                  style="width: 100px"
+                  v-model="price4"
+                ></el-input>
+                圆整),
+              </div>
+              <div class="mb14">
+                待该项实验完成后支付 30%的费用提供实验结果数据,金额为¥
+                <el-input
+                  size="mini"
+                  style="width: 100px"
+                  v-model="price5"
+                ></el-input>
+                元整(大写
+                <el-input
+                  size="mini"
+                  style="width: 100px"
+                  v-model="price6"
+                ></el-input>
+                圆整),
+              </div>
+              <div class="mb14">
+                最后支付10%的费用将提供全部原始数据,金额¥
+                <el-input
+                  size="mini"
+                  style="width: 100px"
+                  v-model="price7"
+                ></el-input>
+                元整(大写
+                <el-input
+                  size="mini"
+                  style="width: 100px"
+                  v-model="price8"
+                ></el-input>
+                圆整)。
+              </div>
+            </div>
+          </div>
+          <p class="mb14">
+            其他未尽事宜,由双方共同友好协商解决,若有其他内容,请在下方说明。
+          </p>
+          <el-input v-model="text" placeholder="输入"></el-input>
+          <div>
+            <el-checkbox v-model="checked3">
+              <el-button type="text">
+                本人已确认以上内容填写无误,若因为本人填写错误导致的试验失败,中心不承担相应责任。
+              </el-button>
+            </el-checkbox>
+          </div>
+        </div>
+      </div>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="onCancel" size="small">取 消</el-button>
+          <el-button
+            :disabled="step == 1"
+            type="primary"
+            @click="onPrev"
+            size="small"
+          >
+            上一步
+          </el-button>
+          <el-button
+            :disabled="step == 3"
+            type="primary"
+            @click="onNext"
+            size="small"
+          >
+            下一步
+          </el-button>
+          <el-button
+            type="primary"
+            :disabled="state.loading || step !== 3"
+            @click="subAdd"
+            size="small"
+          >
+            提 交
+          </el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts">
+  import form1 from "./form1.vue";
+  import form2 from "./form2.vue";
+  import form3 from "./form3.vue";
+  import form4 from "./form4.vue";
+  export default {
+    name: "FrontendWebTest",
+    components: {
+      form1,
+      form2,
+      form3,
+      form4,
+    },
+    data() {
+      return {
+        step: 1,
+        title: "技术服务-预约申请",
+        form: {
+          field1: "",
+          field2: "",
+          field3: "",
+          field4: "",
+          field5: "",
+          field6: "",
+          field7: "",
+          field8: "",
+          field9: "",
+          field10: "",
+          field11: "",
+          field12: "",
+          field13: "",
+          field14: "",
+        },
+        state: {
+          isShowDialog: false,
+          loading: false,
+          dynamicForm: [],
+        },
+        rules: {
+          startTime: [{ required: true, message: "不能为空", trigger: "blur" }],
+        },
+        activeName: "10",
+        formList: [
+          { type: "10", field1: "", fileList2: [], fileList1: [] },
+          { type: "20", field1: "", fileList2: [], fileList1: [] },
+          { type: "30", field1: "", fileList2: [], fileList1: [] },
+          { type: "40", field1: "", fileList2: [], fileList1: [] },
+        ],
+        itemList: [
+          {
+            plat: "Western Blot",
+            proj: "项目1:总蛋白提取及定量",
+            name: "服务费",
+            price: "10",
+            count: 10,
+            total: "10",
+          },
+        ],
+        price1: "",
+        price2: "",
+        price3: "",
+        price4: "",
+        price5: "",
+        price6: "",
+        price7: "",
+        price8: "",
+        text: "",
+        checked1: false,
+        checked2: false,
+        checked3: false,
+      };
+    },
+    methods: {
+      changeField1() {
+        this.form = {
+          field1: "肿瘤研究课题",
+          field2: "课题类型",
+          field3: "",
+          field4: "",
+          field5: "123456",
+          field6: "肿瘤科",
+          field7: "张三",
+          field8: "18801234567",
+          field9: "18801234567@163.com",
+          field10: "肿瘤科",
+          field11: "王雷",
+          field12: "TC12345714",
+          field13: "18801234777",
+          field14: "肿瘤科",
+        };
+      },
+      // 选择技术服务
+      onPrev() {
+        this.step--;
+      },
+      onNext() {
+        this.step++;
+      },
+      async openDialog() {
+        this.state.isShowDialog = true;
+      },
+      onCancel() {
+        this.$refs.editFormRef.clearValidate();
+        this.$refs.editFormRef.resetFields();
+        this.state.isShowDialog = false;
+      },
+      subAdd() {
+        this.$message.success("提交成功");
+        this.step = 1;
+        this.state.isShowDialog = false;
+      },
+      getSummaries(param) {
+        const { columns, data } = param;
+        const sums = [];
+        columns.forEach((column, index) => {
+          if (index === 1) {
+            sums[1] = "合计";
+            return;
+          }
+          const values = data.map((item) => Number(item[column.property]));
+          if (!values.every((value) => isNaN(value))) {
+            sums[4] = values.reduce((prev, curr) => {
+              const value = Number(curr);
+              if (!isNaN(value)) {
+                return prev + curr;
+              } else {
+                return prev;
+              }
+            }, 0);
+            sums[4] += " 元";
+          } else {
+            sums[index] = "";
+          }
+        });
+
+        return sums;
+      },
+    },
+  };
+</script>
+
+<style lang="scss" scoped>
+  :deep(.el-dialog__body) {
+    padding-top: 10px;
+  }
+  .appoint-section {
+    min-height: 450px;
+  }
+  .exper-info-list {
+    h3 {
+      color: #2c405e;
+      font-weight: bold;
+    }
+    .label {
+      width: 100px;
+    }
+  }
+  .step-tit {
+    color: #2c405e;
+    font-weight: bold;
+  }
+</style>

+ 134 - 0
src/views/technical/components/form1.vue

@@ -0,0 +1,134 @@
+<template>
+  <div>
+    <el-form
+      :model="form"
+      ref="form"
+      label-width="80px"
+      :inline="false"
+      size="mini"
+    >
+      <div class="mb20">
+        <h4 class="mb14">一、实验目的</h4>
+        <el-form-item label="实验目的" required>
+          <el-input v-model="form.field1"></el-input>
+        </el-form-item>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">二、实验周期</h4>
+        <el-form-item label="实验目的" required>
+          <el-input
+            disabled
+            value="由实验老师进行填写,如有其他实验安排请填写在第三步的未尽事宜区域;"
+          ></el-input>
+        </el-form-item>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">三、实验内容</h4>
+        <div>
+          <p class="mb10">1.技术服务项目:</p>
+          <el-checkbox-group v-model="checkList">
+            <el-row :gutter="20">
+              <el-col
+                class="mb10"
+                :span="6"
+                v-for="(v, i) in serviceList"
+                :key="i"
+              >
+                <el-checkbox :label="v"></el-checkbox>
+              </el-col>
+            </el-row>
+          </el-checkbox-group>
+        </div>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">四、样本信息</h4>
+        <el-upload
+          v-model:file-list="form.fileList1"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">五、实验技术服务内容(技术路线)(请上传附件)</h4>
+        <el-upload
+          v-model:file-list="form.fileList2"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">六、实验结果交付</h4>
+        <p>
+          1、实验完成后的实验数据及报告将通过电子邮件发送至委托方邮箱或委托方提供U盘或硬盘进行拷贝;
+        </p>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">七、其他附件</h4>
+        <el-upload
+          v-model:file-list="form.fileList3"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script lang="ts">
+  export default {
+    name: "FrontendWebTest",
+    data() {
+      return {
+        form: {
+          field1: "",
+          fileList2: [],
+          fileList1: [],
+          fileList3: [],
+        },
+        serviceList: [
+          "项目1:总蛋白提取及定量",
+          "项目2:核蛋白提取及定量",
+          "项目3:浆蛋白提取及定量",
+          "项目4:膜蛋白提取及定量",
+          "项目5:WB预实验",
+          "项目6:WB正式实验",
+          "项目7:灰度值统计分析",
+          "项目8:组织研磨",
+        ],
+        checkList: [],
+      };
+    },
+    methods: {},
+  };
+</script>
+
+<style lang="scss" scoped>
+  h4 {
+    color: #2c405e;
+    font-weight: bold;
+  }
+  .label {
+    width: 100px;
+  }
+</style>

+ 249 - 0
src/views/technical/components/form2.vue

@@ -0,0 +1,249 @@
+<template>
+  <div>
+    <el-form
+      :model="form"
+      ref="form"
+      label-width="80px"
+      :inline="false"
+      size="mini"
+    >
+      <div class="mb20">
+        <h4 class="mb14">一、实验目的</h4>
+        <el-form-item label="实验目的" required>
+          <el-input v-model="form.field1"></el-input>
+        </el-form-item>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">二、实验周期</h4>
+        <el-form-item label="实验目的" required>
+          <el-input
+            disabled
+            value="由实验老师进行填写,如有其他实验安排请填写在第三步的未尽事宜区域;"
+          ></el-input>
+        </el-form-item>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">三、色谱条件</h4>
+        <div>
+          <div class="table">
+            <div class="header">
+              <el-row>
+                <el-col :span="16">
+                  <div class="p1">色谱条件</div>
+                </el-col>
+                <el-col :span="8">
+                  <div class="p1">备注</div>
+                </el-col>
+              </el-row>
+            </div>
+            <el-row>
+              <el-col class="table-col" :span="8">检测器</el-col>
+              <el-col class="table-col" :span="8">
+                <el-checkbox-group v-model="checked1">
+                  <el-checkbox label="紫外检测器(VWD)"></el-checkbox>
+                  <el-checkbox label="示差检测器"></el-checkbox>
+                </el-checkbox-group>
+              </el-col>
+              <el-col class="table-col" :span="8">
+                <el-input
+                  size="mini"
+                  v-model="val2"
+                  placeholder="请输入"
+                  clearable
+                />
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col class="table-col" :span="8">色谱柱品牌及规格</el-col>
+              <el-col class="table-col" :span="8">
+                <el-input
+                  size="mini"
+                  v-model="val3"
+                  placeholder="请输入"
+                  clearable
+                />
+              </el-col>
+              <el-col class="table-col" :span="8">
+                <el-checkbox-group v-model="checked2">
+                  <el-checkbox label="自备"></el-checkbox>
+                  <el-checkbox label="由本中心提供"></el-checkbox>
+                </el-checkbox-group>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col class="table-col" :span="8">流动相</el-col>
+              <el-col class="table-col" :span="8">
+                <el-select
+                  size="mini"
+                  v-model="select1"
+                  placeholder="请选择"
+                  style="width: 100%"
+                >
+                  <el-option
+                    label="流动相A:乙腈:水 = 1:1(预混)"
+                    value="流动相A:乙腈:水 = 1:1(预混)"
+                  ></el-option>
+                </el-select>
+              </el-col>
+              <el-col class="table-col" :span="8">
+                <el-checkbox-group v-model="checked3">
+                  <el-checkbox label="自备"></el-checkbox>
+                  <el-checkbox label="由本中心提供"></el-checkbox>
+                </el-checkbox-group>
+              </el-col>
+            </el-row>
+            <el-row>
+              <el-col class="table-col" :span="8">流速</el-col>
+              <el-col class="table-col" :span="8">1 ml/min</el-col>
+              <el-col class="table-col" :span="8"></el-col>
+            </el-row>
+            <el-row>
+              <el-col class="table-col" :span="8">温度</el-col>
+              <el-col class="table-col" :span="8">37℃</el-col>
+              <el-col class="table-col" :span="8"></el-col>
+            </el-row>
+            <el-row>
+              <el-col class="table-col" :span="8">进样量</el-col>
+              <el-col class="table-col" :span="8">20μl</el-col>
+              <el-col class="table-col" :span="8"></el-col>
+            </el-row>
+            <el-row>
+              <el-col class="table-col" :span="8">色谱方法</el-col>
+              <el-col class="table-col" :span="8">
+                <el-select
+                  size="mini"
+                  v-model="select1"
+                  placeholder="请选择"
+                  style="width: 100%"
+                >
+                  <el-option
+                    label="流动相A:乙腈:水 = 1:1(预混)"
+                    value="流动相A:乙腈:水 = 1:1(预混)"
+                  ></el-option>
+                </el-select>
+              </el-col>
+              <el-col class="table-col" :span="8"></el-col>
+            </el-row>
+          </div>
+          <p>
+            注:色谱条件由委托人提供并明确,实验过程中可由双方协商进行调整。
+          </p>
+        </div>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">四、样本信息</h4>
+        <el-upload
+          v-model:file-list="form.fileList1"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">五、实验技术服务内容(技术路线)(请上传附件)</h4>
+        <el-upload
+          v-model:file-list="form.fileList2"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">六、实验结果交付</h4>
+        <p>
+          1、实验完成后的实验数据及报告将通过电子邮件发送至委托方邮箱或委托方提供U盘或硬盘进行拷贝;
+        </p>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">七、其他附件</h4>
+        <el-upload
+          v-model:file-list="form.fileList3"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script lang="ts">
+  export default {
+    name: "FrontendWebTest",
+    data() {
+      return {
+        form: {
+          field1: "",
+          fileList2: [],
+          fileList1: [],
+          fileList3: [],
+        },
+        serviceList: [
+          "项目1:总蛋白提取及定量",
+          "项目2:核蛋白提取及定量",
+          "项目3:浆蛋白提取及定量",
+          "项目4:膜蛋白提取及定量",
+          "项目5:WB预实验",
+          "项目6:WB正式实验",
+          "项目7:灰度值统计分析",
+          "项目8:组织研磨",
+        ],
+        checkList: [],
+        checked1: [],
+        checked2: [],
+        checked3: [],
+        select1: "",
+        val2: "",
+        val3: "",
+      };
+    },
+    methods: {},
+  };
+</script>
+
+<style lang="scss" scoped>
+  h4 {
+    color: #2c405e;
+    font-weight: bold;
+  }
+  .label {
+    width: 100px;
+  }
+  .header {
+    padding: 10px 0;
+    background: #f3f6fb;
+    width: 100%;
+    .p1 {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+  }
+  .table-col {
+    padding: 10px 0;
+    border: 1px solid #ccc;
+    height: 44px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0 20px;
+  }
+</style>

+ 151 - 0
src/views/technical/components/form3.vue

@@ -0,0 +1,151 @@
+<template>
+  <div>
+    <el-form
+      :model="form"
+      ref="form"
+      label-width="80px"
+      :inline="false"
+      size="mini"
+    >
+      <div class="mb20">
+        <h4 class="mb14">一、实验目的</h4>
+        <el-form-item label="实验目的" required>
+          <el-input v-model="form.field1"></el-input>
+        </el-form-item>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">二、实验周期</h4>
+        <el-form-item label="实验目的" required>
+          <el-input
+            disabled
+            value="由实验老师进行填写,如有其他实验安排请填写在第三步的未尽事宜区域;"
+          ></el-input>
+        </el-form-item>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">三、实验内容</h4>
+        <div>
+          <p class="mb10">1.技术服务项目:</p>
+          <el-checkbox-group v-model="checkList" class="mb10">
+            <el-row :gutter="20">
+              <el-col
+                :span="6"
+                v-for="(v, i) in serviceList"
+                :key="i"
+                class="mb10"
+              >
+                <el-checkbox :label="v"></el-checkbox>
+              </el-col>
+            </el-row>
+          </el-checkbox-group>
+        </div>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">四、样本信息</h4>
+        <el-upload
+          v-model:file-list="form.fileList1"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">五、实验技术服务内容(技术路线)(请上传附件)</h4>
+        <el-upload
+          v-model:file-list="form.fileList2"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+      <div>
+        <h4 class="mb14">六、实验结果交付</h4>
+        <p class="mb14">1、请保证原材料新鲜,并由合适的方法保存;</p>
+        <p class="mb14">2、请提供足够的样品,便于实验;</p>
+        <p class="mb14">
+          3、样品如需长途运输,建议使用干冰运输或加入DNA/RNA保护剂(血液样本不建议加DNA/RNA保护剂),请告知运输情况;
+        </p>
+        <p class="mb14">
+          4、实验完成后,如需返还样品,请提前告知,否则本中心一律视为废物处置;
+        </p>
+        <p class="mb14">5、本中心不接收传染性样品,请确认您的样品不具有传染性;</p>
+        <p class="mb14">
+          6、DNA/TotalRNA提取服务收到合格样本之日起7个工作日内完成,样本量大工作周期顺延;
+        </p>
+        <p class="mb14">
+          7、逆转录服务收到合格样本之日起3个工作日内完成,样本量大工作周期顺延;
+        </p>
+        <p class="mb14">
+          8、荧光定量PCR服务收到合格样本之日起10个工作日内完成,样本量大工作周期顺延,荧光定量PCR默认扩增效率100%,不制作标准曲线,均采用2-∆∆CT法分析,如需制作标准曲线费用另计;
+        </p>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">七、实验结果交付</h4>
+        <p>
+          1、实验完成后的实验数据及报告将通过电子邮件发送至委托方邮箱或委托方提供U盘或硬盘进行拷贝;
+        </p>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">八、其他附件</h4>
+        <el-upload
+          v-model:file-list="form.fileList3"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script lang="ts">
+  export default {
+    name: "FrontendWebTest",
+    data() {
+      return {
+        form: {
+          field1: "",
+          fileList2: [],
+          fileList1: [],
+          fileList3: [],
+        },
+        serviceList: [
+          "项目1:基因组DNA提取",
+          "项目2:Total RNA提取",
+          "项目3:逆转录 ",
+          "项目4:荧光定量PCR",
+        ],
+        checkList: [],
+      };
+    },
+    methods: {},
+  };
+</script>
+
+<style lang="scss" scoped>
+  h4 {
+    color: #2c405e;
+    font-weight: bold;
+  }
+  .label {
+    width: 100px;
+  }
+</style>

+ 152 - 0
src/views/technical/components/form4.vue

@@ -0,0 +1,152 @@
+<template>
+  <div>
+    <el-form
+      :model="form"
+      ref="form"
+      label-width="80px"
+      :inline="false"
+      size="mini"
+    >
+      <div class="mb20">
+        <h4 class="mb14">一、实验目的</h4>
+        <el-form-item label="实验目的" required>
+          <el-input v-model="form.field1"></el-input>
+        </el-form-item>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">二、实验周期</h4>
+        <el-form-item label="实验目的" required>
+          <el-input
+            disabled
+            value="由实验老师进行填写,如有其他实验安排请填写在第三步的未尽事宜区域;"
+          ></el-input>
+        </el-form-item>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">三、实验内容</h4>
+        <div>
+          <p class="mb10">1.技术服务项目:</p>
+          <el-checkbox-group v-model="checkList" class="mb10">
+            <el-row :gutter="20">
+              <el-col
+                :span="6"
+                v-for="(v, i) in serviceList"
+                :key="i"
+                class="mb10"
+              >
+                <el-checkbox :label="v"></el-checkbox>
+              </el-col>
+            </el-row>
+          </el-checkbox-group>
+        </div>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">四、样本信息</h4>
+        <el-upload
+          v-model:file-list="form.fileList1"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">五、实验技术服务内容(技术路线)(请上传附件)</h4>
+        <el-upload
+          v-model:file-list="form.fileList2"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+      <div>
+        <h4 class="mb14">六、实验结果交付</h4>
+        <p class="mb14">
+          1、收取样品时双方确认是否合格。对不合格/不完全合格样品,拒收样本。在委托人坚持尝试实验情况下,按正常实验收取技术服务费用。
+        </p>
+        <p class="mb14">
+          2、若委托人对实验结果有异议需重复实验的须支付相应技术服务费用。
+        </p>
+        <p class="mb14">
+          3、委托人提供的实验材料为特殊珍贵样品的,须进行特殊说明,否则视为一般样品。
+        </p>
+        <p class="mb14">
+          4、乙方损失合格标本,退还相应费用,不可抗拒的原因除外。(本处损失是指因乙方工作人员不慎造成的样本溢洒、样本丢失等,且导致样本量不足以完成实验的情况,不包括正常情况下进行实验所造成的样本量的减少。)
+        </p>
+        <p class="mb14">
+          5、如因实验材料等非乙方原因造成某实验步骤失败,使服务提前终止,已启动的服务项目仍正常收费。
+        </p>
+        <p class="mb14">
+          6、DNA/6、鉴于科学研究存在不确定性,针对其开展的技术服务环节众多,甚至具有探索性质,故双方应本着科学、公正、实事求是的原则,共同促进技术服务的完成,不能过于苛刻或显失公平。
+        </p>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">七、实验结果交付</h4>
+        <p>
+          1、实验完成后的实验数据及报告将通过电子邮件发送至委托方邮箱或委托方提供U盘或硬盘进行拷贝;
+        </p>
+      </div>
+      <div class="mb20">
+        <h4 class="mb14">八、其他附件</h4>
+        <el-upload
+          v-model:file-list="form.fileList3"
+          class="upload-demo"
+          action="http://192.168.0.218:9933/weedfs/upload"
+          multiple
+          :limit="3"
+        >
+          <el-button type="primary" size="mini">上传附件</el-button>
+          <template #tip>
+            <div class="el-upload__tip">文件大小不能超过20MB</div>
+          </template>
+        </el-upload>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script lang="ts">
+  export default {
+    name: "FrontendWebTest",
+    data() {
+      return {
+        form: {
+          field1: "",
+          fileList2: [],
+          fileList1: [],
+          fileList3: [],
+        },
+        serviceList: [
+          "项目1:固定+脱水+透明+包埋",
+          "项目2:石蜡切片",
+          "项目3:冰冻切片+包埋",
+          "项目4:石蜡切片HE染色",
+          "项目5:普通免疫组化染色",
+        ],
+        checkList: [],
+      };
+    },
+    methods: {},
+  };
+</script>
+
+<style lang="scss" scoped>
+  h4 {
+    color: #2c405e;
+    font-weight: bold;
+  }
+  .label {
+    width: 100px;
+  }
+</style>

+ 511 - 0
src/views/technical/service.vue

@@ -0,0 +1,511 @@
+<template>
+  <div class="instr-container">
+    <div class="search-wrap"></div>
+    <div class="common-container">
+      <section class="section-container">
+        <div class="service-list">
+          <div class="service-list-header">
+            <h4 class="title">技术服务</h4>
+          </div>
+          <el-empty
+            v-if="serviceDataList.length == 0"
+            description="很抱歉,没有找到相关的仪器~"
+          ></el-empty>
+          <div v-else>
+            <div class="flex list-header">
+              <div>共{{ serviceDataList.length }}项技术服务</div>
+              <div class="btn" @click="handleAppoint">
+                需求提报({{ needList.length }})
+              </div>
+            </div>
+            <div class="instr-item" v-for="v in serviceDataList" :key="v.id">
+              <div class="img-item">
+                <img
+                  src="../../assets/img/service.png"
+                  style="width: 100%"
+                  alt=""
+                />
+              </div>
+              <div class="text-item">
+                <p class="name">{{ v.name }}</p>
+                <div class="info" style="flex: 1">
+                  <div class="info-txt">{{ v.content }}</div>
+                </div>
+                <div class="info">
+                  <div class="info-title">技术服务平台:</div>
+                  <div class="info-txt">
+                    <div>{{ v.plat }} - {{ v.user }}</div>
+                    <div class="btns flex">
+                      <div class="btn btn1">详情</div>
+                      <div class="btn btn2" @click="joinNeedList(v.id)">
+                        加入需求
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+              <!-- <div class="appoint-item">
+                <div class="mb20">
+                  <el-button
+                    type="primary"
+                    size="default"
+                    v-if="v.instStatus == '10' && v.isAppointment == '10'"
+                    @click="handleAppoint(v)"
+                  >
+                    使用预约
+                  </el-button>
+                </div>
+                <div>
+                  <el-button
+                    type="primary"
+                    plain
+                    size="default"
+                    @click="linkToDetails(v)"
+                  >
+                    查看详情
+                  </el-button>
+                </div>
+              </div> -->
+            </div>
+          </div>
+          <div class="pagination">
+            <el-pagination
+              background
+              @size-change="handleSizeChange"
+              @current-change="handleCurrentChange"
+              :current-page="searchForm.pageNum"
+              :page-sizes="[10, 50, 100]"
+              :page-size="searchForm.pageSize"
+              layout="total, sizes, prev, pager, next, jumper"
+              :total="total"
+            ></el-pagination>
+          </div>
+        </div>
+      </section>
+    </div>
+    <appoint ref="appointRef"></appoint>
+  </div>
+</template>
+
+<script name="service">
+  import to from "await-to-js";
+  import { getToken } from "@/utils/auth";
+  import { Loading } from "element-ui";
+  import { getInstrList, getInstNameEnCount } from "@/api/instr/index";
+  import appoint from "./components/edit.vue";
+  export default {
+    name: "equipment",
+    components: { appoint },
+    data() {
+      return {
+        platFilterExpand: false,
+        instrTypeFilterExpand: false,
+        searchForm: {
+          searchText: "",
+          laboratoryName: "",
+          instClassDesc: "",
+          instNameEn: "",
+          pageNum: 1,
+          pageSize: 10,
+        },
+        needList: [],
+        total: 4,
+        serviceDataList: [
+          {
+            id: 1,
+            name: "Western Blot相关实验",
+            content:
+              "Western Blot(蛋白质印迹法)是一种广泛应用于分子生物学、生物化学和免疫遗传学中的实验技术,用于检测样品中特定蛋白质的存在、大小和表达量。包含样品制备、SDS - PAGE 电泳、蛋白质转印、抗体孵育、检测与分析等步骤。",
+            plat: "细胞平台",
+            user: "张老师",
+          },
+          {
+            id: 2,
+            name: "高效液相色谱实验",
+            content:
+              "高效液相色谱(High - Performance Liquid Chromatography,HPLC)实验是一种重要的分离分析技术,广泛应用于化学、生物、医药等众多领域,用于分离、鉴定和定量分析各种复杂混合物中的化学成分。",
+            plat: "光学平台",
+            user: "张老师",
+          },
+          {
+            id: 3,
+            name: "核酸提取扩增相关实验",
+            content:
+              "核酸包括 DNA 和 RNA,提取的基本原理是利用核酸与其他细胞成分在物理和化学性质上的差异进行分离。",
+            plat: "分子平台",
+            user: "张老师",
+          },
+          {
+            id: 4,
+            name: "组织与病理学相关实验",
+            content:
+              "组织样本采集是组织与病理学实验的基础。目的是获取能够代表病变或正常组织特征的样本,用于后续的病理诊断和研究。采集过程需要遵循无菌、快速、准确的原则。",
+            plat: "病理平台",
+            user: "张老师",
+          },
+        ],
+        laboratoryNameOptions: [],
+        instClassDescOptions: [],
+        instNameEnOptions: [],
+        options: {
+          text: "正在加载中,请稍后...",
+          background: "rgba(0, 0, 0, 0.6)",
+        },
+      };
+    },
+    created() {},
+
+    mounted() {
+      // this.getInstrData();
+    },
+
+    methods: {
+      joinNeedList(id) {
+        this.needList.push(id);
+        this.needList = [...new Set(this.needList)];
+        this.$message.success("加入成功");
+      },
+      handleAppoint() {
+        this.$refs.appointRef.openDialog();
+        // const token = getToken();
+        // if (!token) {
+        //   return this.$router.push("/login?redirect=/appointment/equipment");
+        // }
+        // this.$refs.appointRef.openDialog(row);
+      },
+      // 获取型号数量
+      async getInstNameEnCountData() {
+        const params = {
+          instClassDesc: this.searchForm.instClassDesc,
+          laboratoryName: this.searchForm.laboratoryName,
+          searchText: this.searchForm.searchText,
+        };
+        const [err, res] = await to(getInstNameEnCount(params));
+        if (err) return;
+        if (res.code == 200) {
+          this.instNameEnOptions = res.data;
+        }
+      },
+      // 上方搜索查询
+      async globalSearch() {
+        this.searchForm.pageNum = 1;
+        this.searchForm.instClassDesc = "";
+        this.searchForm.laboratoryName = "";
+        this.searchForm.instNameEn = "";
+        this.getInstrData();
+      },
+      async getInstrData() {
+        // Loading.service(this.loadingOption);
+        // const [err, res] = await to(getInstrList(this.searchForm));
+        // setTimeout(() => {
+        //   Loading.service(this.loadingOption).close();
+        // });
+        // if (err) return;
+        // if (res.code == 200) {
+        //   this.serviceDataList = res.data.list;
+        //   this.total = res.data.total;
+        //   this.laboratoryNameOptions = this.objTransforArr(
+        //     res.data.count.laboratoryName
+        //   );
+        //   this.instClassDescOptions = this.objTransforArr(
+        //     res.data.count.instClassDesc
+        //   );
+        //   this.getInstNameEnCountData();
+        // }
+      },
+      // 对象转数组
+      objTransforArr(obj) {
+        const arr = Object.entries(obj).map(([key, value]) => ({
+          name: key,
+          count: value,
+        }));
+        return arr;
+      },
+      // 删除查询条件
+      closeTag(type) {
+        switch (type) {
+          case "laboratoryName":
+            this.searchForm.laboratoryName = "";
+            break;
+          case "instClassDesc":
+            this.searchForm.instClassDesc = "";
+            break;
+          case "instNameEn":
+            this.searchForm.instNameEn = "";
+            break;
+        }
+        this.searchForm.pageNum = 1;
+        this.getInstrData();
+      },
+      // 展开 合并
+      handleExpandFilter(type = "plat" | "instrType") {
+        if (type === "plat") {
+          this.platFilterExpand = !this.platFilterExpand;
+        } else if (type === "instrType") {
+          this.instrTypeFilterExpand = !this.instrTypeFilterExpand;
+        }
+      },
+      // 选择查询条件
+      selectFilterItem(name, val) {
+        switch (val) {
+          case "laboratoryName":
+            if (this.searchForm.laboratoryName != name) {
+              this.searchForm.laboratoryName = name;
+              this.searchForm.pageNum = 1;
+              this.getInstrData();
+            }
+            break;
+          case "instClassDesc":
+            if (this.searchForm.instClassDesc != name) {
+              this.searchForm.instClassDesc = name;
+              this.searchForm.pageNum = 1;
+              this.getInstrData();
+            }
+            break;
+          case "instNameEn":
+            if (this.searchForm.instNameEn != name) {
+              this.searchForm.instNameEn = name;
+              this.searchForm.pageNum = 1;
+              this.getInstrData();
+            }
+            break;
+        }
+      },
+      handleSizeChange(val) {
+        this.searchForm.pageSize = val;
+        this.getInstrData();
+      },
+      handleCurrentChange(val) {
+        this.searchForm.pageNum = val;
+        this.getInstrData();
+      },
+      linkToDetails(v) {
+        this.$router.push("/appointment/equipment-details?id=" + v.id);
+      },
+    },
+  };
+</script>
+
+<style lang="scss" scoped>
+  .search-wrap {
+    width: 100%;
+    height: 240px;
+    position: relative;
+    &::after {
+      display: block;
+      content: "";
+      width: 100%;
+      height: 100%;
+      position: absolute;
+      top: 0;
+      left: 0;
+      background: url("../../assets/img/equipment-banner1.png") center;
+      background-size: 100% 240px;
+    }
+  }
+  .section-container {
+    width: 1200px;
+    margin: 0 auto;
+  }
+  .filter-wrap {
+    width: 100%;
+    .filter-item {
+      width: 100%;
+      min-height: 48px;
+      display: flex;
+      border-bottom: 2px dashed rgba(112, 112, 112, 0.18);
+      &:last-child {
+        border-bottom: none;
+      }
+    }
+
+    .left-tit {
+      width: 120px;
+      background: #f1f1f1;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-weight: bold;
+    }
+    .right-filter-content {
+      flex: 1;
+      padding: 9px 24px 9px 36px;
+      display: flex;
+      flex-wrap: wrap;
+      position: relative;
+      .list {
+        max-height: 120px;
+        overflow: auto;
+        width: 100%;
+        display: flex;
+        flex-wrap: wrap;
+        // &::-webkit-scrollbar {
+        //   display: none;
+        // }
+        .dragger-container {
+          position: absolute;
+          width: 6px;
+          top: 36px;
+          right: 34px;
+          height: 84px;
+          background: #ccc;
+          border-radius: 20px;
+          .dragger-bar {
+            position: absolute;
+            width: 6px;
+            height: 60px;
+            top: 0px;
+            border-radius: 20px;
+            background: rgba(0, 0, 0, 0.75);
+          }
+        }
+      }
+      .name {
+        font-size: 14px;
+        margin: 5px 30px 5px 0;
+        cursor: pointer;
+        &:hover {
+          text-decoration: underline;
+          color: #1677ff;
+        }
+        &.avtive {
+          text-decoration: underline;
+          color: #1677ff;
+        }
+      }
+      .more-item {
+        position: absolute;
+        top: 12px;
+        right: 0;
+        padding-right: 16px;
+        font-size: 14px;
+        cursor: pointer;
+        z-index: 2;
+        i {
+          color: #b1b1b1;
+        }
+      }
+    }
+  }
+  .service-list-header {
+    padding: 15px 18px;
+    display: flex;
+    border: 1px solid rgba(112, 112, 112, 0.06);
+    position: relative;
+    .title {
+      width: 120px;
+      font-size: 16px;
+      color: #333;
+      font-weight: 700;
+      padding-right: 18px;
+      padding-top: 3px;
+      flex: 0 0 120px;
+    }
+    .filter-wrap {
+      min-height: 45px;
+      padding-right: 80px;
+    }
+  }
+  .service-list {
+    background: #fff;
+    border-radius: 6px;
+    margin-top: 20px;
+    min-height: 200px;
+    .list-header {
+      padding: 12px 30px 10px;
+      border-bottom: 1px solid rgba(112, 112, 112, 0.06);
+      align-items: center;
+      justify-content: space-between;
+      .btn {
+        cursor: pointer;
+        background: #facd91;
+        border-top-left-radius: 8px;
+        border-top-right-radius: 8px;
+        padding: 8px 50px;
+      }
+    }
+    .instr-item {
+      padding: 24px 30px;
+      display: flex;
+      border-bottom: 1px solid rgba(112, 112, 112, 0.06);
+      .img-item {
+        width: 180px;
+        height: 180px;
+        border-radius: 6px;
+        overflow: hidden;
+        margin-right: 18px;
+        position: relative;
+        background: #f3f6fb;
+      }
+      .text-item {
+        flex: 1;
+        width: 0;
+        font-size: 14px;
+        padding-top: 6px;
+        display: flex;
+        flex-direction: column;
+        .name {
+          font-weight: bold;
+          font-size: 20px;
+          margin-bottom: 12px;
+        }
+        .info {
+          color: #666;
+          display: flex;
+          font-size: 14px;
+          margin-bottom: 8px;
+          .info-title {
+            width: 100px;
+          }
+          .info-txt {
+            width: 0;
+            flex: 1;
+            position: relative;
+            .btns {
+              position: absolute;
+              right: 0;
+              top: -8px;
+            }
+            .btn {
+              width: 90px;
+              padding: 8px;
+              cursor: pointer;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              &.btn1 {
+                border-top-left-radius: 8px;
+                border-bottom-left-radius: 8px;
+                background: #facd91;
+              }
+              &.btn2 {
+                color: #fff;
+                border-top-right-radius: 8px;
+                border-bottom-right-radius: 8px;
+                background: #1c9bfd;
+              }
+            }
+          }
+        }
+      }
+      .appoint-item {
+        width: 120px;
+        padding: 0 0 0 18px;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+      }
+    }
+  }
+  .pagination {
+    width: 100%;
+    height: 50px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  div {
+    color: #333;
+  }
+</style>