前端-后台管理项目单页面编码思维

时间:2024-11-27 19:19:55


前端-后台管理项目单页面编码思维_数据

开发这样一个页面并不难,提高页面的可复用性从而节约时间成本,这应该是每位同事的必修课。

class为组件预设样式,放在文末展示

页面基础布局:

前端-后台管理项目单页面编码思维_标签页_02

 预设参数

interface State {
  tableData: any[];   // 列表数据
  loading: boolean;   // 列表加载状态
  searchParams: {     // 筛选参数
    keyword: string;
  };
  page: {             // 页码配置
    page: number;
    size: number;
    total: number;
  };
}
const state = reactive<State>({
  tableData: [],
  loading: true,
  searchParams: {
    keyword: "",
  },
  page: {
    page: 1,
    size: 10,
    total: 0,
  },
});

完善搜索栏

前端-后台管理项目单页面编码思维_表数据_03

 

预设方法:

// 搜索/获取列表数据
const searchListByParams = () => {
  state.loading = true;
  let newParams = JSON.parse(
    JSON.stringify({
      ...state.searchParams,
      ...state.page,
    })
  );
  delete newParams.total;
  // 获取列表数据
  // getList(newParams).then((res: any) => {
  // });
  state.loading = false;
};
// 重置表单
const reset = () => {
  state.searchParams.keyword = "";
  searchListByParams();
};
// 翻页
const handleCurrentChange = () => {
  searchListByParams();
};
// 改变每页显示条数
const handleSizeChange = () => {
  searchListByParams();
};

标签页配置:

// tab页
const tabsLabel = [
  { label: "登录日志", name: "0" },
  { label: "请求日志", name: "1" },
  { label: "执行日志", name: "2" },
  { label: "异常日志", name: "3" },
  { label: "数据接入日志", name: "4" },
  { label: "数据交换日志", name: "5" },
];
const logTabIndex = ref<string>("0");
const logTabChange = (tab: any) => {
  // 切换tab下标
  logTabIndex.value = tab.index;
  searchListByParams();
};

 标签页填充:

前端-后台管理项目单页面编码思维_设计规范_04

标签页和表格【表头】的关系,应当是一 一对应的,在设计表格时要考虑到这种情况

前端-后台管理项目单页面编码思维_标签页_05

即:不同的tab页对应着不同的表格

前端-后台管理项目单页面编码思维_标签页_06

同时要考虑数据回显的方式,后端返回的数据是直接展示的明文,还是需要到字典表查询的键名。

表格【表头】设计:

/**表头配置
 * @prop 对应的字段
 * @label 显示名称
 * @propMap 根据返回值映射名称
 * @colorMap 根据返回值映射字体颜色
 * */ 
const columnLabel: any = [
  // 登录日志
  [
    { prop: 'xxx', label: '姓名' },
    { prop: 'xxx', label: '用户名' },
    { prop: 'xxx', label: '操作类型', 
      propMap: {
        0: '登录',
        1: '退出',
      },
      colorMap: {
        0: '#33f',
        1: '#3f3',
      }
    },
    { prop: 'xxx', label: '操作时间' },
    { prop: 'xxx', label: '操作模块' },
    { prop: 'xxx', label: '操作内容' },
    { prop: 'xxx', label: 'IP地址' },
  ],
  // 请求日志
  [
    { prop: 'xxx', label: '用户名称' },
    { prop: 'xxx', label: '请求接口' },
    { prop: 'xxx', label: '请求方式' },
    { prop: 'xxx', label: '请求路径' },
    { prop: 'xxx', label: '请求时间' },
    { prop: 'xxx', label: '返回状态' },
    { prop: 'xxx', label: 'IP地址' },
  ],
  // 执行日志
  [

  ],
  // 异常日志
  [

  ],
  // 数据接入日志
  [

  ],
  // 数据交换日志
  [

  ],
]

表头配置与表格组件结合:

<!-- 表格 -->
<el-table
  v-loading="state.loading"
  class="tb-list mis-margin-top"
  :data="state.tableData"
  highlight-current-row
  height="calc(100% - 56px - 48px)"
>
  <el-table-column
    type="index"
    label="序号"
    width="80"
    align="center"
  />
  <el-table-column
    v-for="(item, index) of columnLabel[logTabIndex]"
    :key="logTabIndex + index"
    :prop="item.prop"
    :label="item.label"
    align="center"
    show-overflow-tooltip
  >
    <template #default="{ row }">
      <span :style="{
        color: item.colorMap ? item.colorMap[row[item.prop]] : ''
      }">
        {{ item.propMap ? item.propMap[row[item.prop]] : row[item.prop] }}
      </span>
    </template>
  </el-table-column>
</el-table>

 演示效果:

前端-后台管理项目单页面编码思维_设计规范_07

前端-后台管理项目单页面编码思维_设计规范_08

 需要操作项怎么办,加

前端-后台管理项目单页面编码思维_标签页_09

表格设计:

可以在这个基础上加判断条件,给按钮置灰、禁用等

前端-后台管理项目单页面编码思维_设计规范_10

演示效果:

前端-后台管理项目单页面编码思维_表数据_11

前端-后台管理项目单页面编码思维_数据_12

登录日志有,请求日志无,需要就加,不需要不加

同理,Switch 切换等元素,也可以按需配置

前端-后台管理项目单页面编码思维_表数据_13

当我们要添加某些元素时,一定要思路清晰。如果是添加一整列,那就是表头相关,这样配置出来的元素都是整列整列的

前端-后台管理项目单页面编码思维_数据_14

如果你要配置的元素不包含整列,就不宜放在表头文件中配置

前端-后台管理项目单页面编码思维_数据_15

 最后加上分页组件,这个模板就开发好了。

我是一个非常喜欢使用循环的人,本文表达的重点在表头配置上,对于一些样式相同的组件,我都会采用表头循环的方式来做。

前端-后台管理项目单页面编码思维_数据_16

前端-后台管理项目单页面编码思维_标签页_17

开发中涉及的数十种设备, 都是同一个组件,用不同的表头文件来回显数据

我们看一段高度组件化的表头代码

getList(newParams).then((res: any) => {
    if (!res.data) return;
    // 根据专项索引设置表头,在../config/dialogBasic.js 中配置表头
    // 专项名称为heat时,自动引入表头 【deviceInfo + 专项名称】,显示供热专项的设备信息
    baseData.value = basiLabel["deviceInfo" + props.bizTypeCode]?.map(
      (v: any) => {
        return {
          ...v,
          val: v.propList
            ? v.propList.map((itm: any) => (itm = res.data[itm]))
            : res.data[v.prop] !== null
              ? res.data[v.prop]
              : "",
        };
      }
    );

这部分就不解释了, 万变不离其宗

这样设计组件有一个好处,方便同事之间交接代码。所有的页面都可以是同一套模板,同事看了你一个页面的代码就明白了你所有的页面,在多人团队中显得尤为重要。

下面是预设css样式,仅供参考:

.mis-pager-contianer {
  position: relative;
  height: 100%;
  .el-main {
    --el-main-padding: 0 !important;
    padding-left: 16px;
    padding-right: 20px;
  }
  .input-search {
    padding-top: 15px;
    :deep(.el-input__wrapper) {
      border-radius: 15px;
    }
  }
  .playVdeo {
    width: 100%;
    height: 95%;
    align-items: center;
    border-radius: 0.15625rem;
    box-shadow: var(--el-box-shadow-light);
    .v-title {
      width: 100%;
      z-index: 121;
      text-align: center;
      background: rgba(0, 0, 0, 0.39);
      margin-bottom: 20px;
      padding: 0 20px;
      display: flex;
      justify-content: space-between;
      font-size: 16px;
      font-family: PingFang SC;
      color: #ffffff;
    }
    .v-box {
      width: 100%;
      height: 100%;
    }
  }

  .no-video {
    width: 100%;
    height: 100%;
    background: #000;
    color: #f00;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    border-radius: 3px;
  }
  // 树结构筛选
  .filter-tree {
    padding-top: 17px;
    margin-right: 10px;
    height: 100%;
    font-size: 14px;
    font-family: PingFang SC;
    font-weight: 500;
    color: #16171c;
    .flag-def {
      width: 38px;
      height: 20px;
      background: rgba(56, 128, 234, 0.12);
      border: 1px solid #3880ea;
      border-radius: 2px;
      font-size: 12px;
      font-family: PingFang SC;
      font-weight: 500;
      line-height: 20px;
      text-align: center;
      color: #3880ea;
      margin: 0 8px;
    }
    .font {
      position: absolute;
      right: 0;
    }
    // 设置节点高度
    :deep(.el-tree-node__content) {
      height: 40px;
    }
    :deep(.el-tree-node__content:hover) {
      background-color: #eaf2ff;
    }
  }
  // 四宫格
  .four-box {
    /* grid是二维布局,行 * 列 的网格 */
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
    min-height: 550px;
    .four-item {
      width: 43%;
      height: 270px;
      margin: 5px 15px;
      border: 1px solid rgb(161, 153, 161);
      position: relative;
      .item-name {
        width: 100%;
        height: 30px;
        padding: 0 10px;
        color: #2d7dff;
        position: absolute;
        bottom: 0px;
        background: rgba(0, 0, 0, 0.39);
        display: flex;
        justify-content: space-between;
        font-size: 16px;
        font-family: PingFang SC;
        font-weight: bold;
        line-height: 30px;
        color: #ffffff;
        > div {
          color: #00b89b;
        }
      }
    }
  }
  // 九宫格
  .nine-box {
    /* grid是二维布局,行 * 列 的网格 */
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
    min-height: 550px;
    border: #3880ea 1px solid;
    .nine-item {
      width: 33%;
      height: 230px;
      border: 1px solid plum;
    }
  }
}

如有纰漏欢迎指摘