Skip to content

🔌 API文档

l-pc-front 项目API接口与数据通信完整指南


📋 API架构概览

通信架构图

┌─────────────────────────────────────────────────────────────┐
│                    客户端 (Frontend)                       │
│  Vue组件 → Vuex状态 → HTTP客户端 → 拦截器 → 认证处理      │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                    网关层 (Gateway)                         │
│  代理转发 → 路由匹配 → 协议转换 → 负载均衡                │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│                    服务端 (Backend)                        │
│  业务服务 → 数据库 → 缓存 → 消息队列 → 认证服务           │
└─────────────────────────────────────────────────────────────┘

🔧 HTTP客户端封装

1. 核心配置 (src/common/http.js)

Axios实例配置

javascript
import axios from "axios";
import store from "../store/index";
import Vue from "vue";
import { Message } from "element-ui";
import loginDialog from "../components/ui/login-dialog/login-dialog.vue";

// 基础配置
const instance = axios.create({
  baseURL: baseURL,           // 动态基础URL
  timeout: 1000 * 60,         // 60秒超时
  withCredentials: true,      // 跨域凭证
});

// 请求拦截器
instance.interceptors.request.use(
  function (config) {
    // 自动添加认证票据
    const bx_auth_ticket = sessionStorage.getItem("bx_auth_ticket");
    if (bx_auth_ticket) {
      config.headers.set("bx_auth_ticket", bx_auth_ticket);
      config.headers.set("bx-auth-ticket", bx_auth_ticket);
    }
    
    // 可以在这里添加其他请求头
    config.headers["X-Requested-With"] = "XMLHttpRequest";
    
    return config;
  },
  function (error) {
    return Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  function (response) {
    // 429: 请求过多
    if (response.status === 429) {
      window.top.limitingTips();
    }
    
    // 处理业务状态码
    if (response.data.state === "FAILURE") {
      handleBusinessError(response.data);
      return response;
    }
    
    // 统一响应格式
    response.body = response.data;
    return response;
  },
  function (error) {
    // 网络错误、超时等
    return Promise.reject(error);
  }
);

// 业务错误处理
function handleBusinessError(data) {
  const { resultCode, resultMessage } = data;
  
  switch (resultCode) {
    case "0011": // 认证失败
      handleAuthFailure();
      break;
    case "0000": // 一般错误
      if (sessionStorage.getItem("need_login_flag") !== "need_login") {
        Message.error(resultMessage);
      }
      break;
    case "9998": // 特殊状态码
      // 静默处理
      break;
    default:
      if (resultMessage && resultMessage.includes("sql语句执行异常")) {
        console.error(resultMessage);
      } else if (sessionStorage.getItem("need_login_flag") !== "need_login") {
        Message.error(resultMessage);
      }
  }
}

// 认证失败处理
function handleAuthFailure() {
  store && store.commit("clearSrvCols");
  
  if (process.env.NODE_ENV === "development" || window.self === window.top) {
    // 开发环境或顶层窗口:显示登录弹窗
    showLoginDialog();
  } else if (window.top?.layer) {
    // iframe环境:使用layer弹窗
    showLayerLogin();
  } else {
    // 其他环境:跳转登录页
    redirectToLogin();
  }
}

export const $http = instance;

2. 快捷方法

javascript
// 查询单条数据
export async function $selectOne(url, req) {
  const res = await $http.post(url, req);
  if (res?.data?.state === "SUCCESS") {
    if (res.data?.data?.length > 0) {
      return { ok: true, data: res.data.data[0] };
    } else {
      return { ok: false, data: {}, msg: "未查询到数据" };
    }
  } else {
    return { ok: false, data: {}, msg: res?.data?.resultMessage || "请求失败" };
  }
}

// 查询列表数据
export async function $selectList(url, req) {
  const res = await $http.post(url, req);
  if (res?.data?.state === "SUCCESS") {
    return { 
      ok: true, 
      data: res.data.data, 
      page: res.data.page 
    };
  } else {
    return { 
      ok: false, 
      data: [], 
      msg: res?.data?.resultMessage || "请求失败" 
    };
  }
}

// 删除数据
export const $delete = async ({ app, service, key = "id", value = "" }) => {
  if (!value) return { ok: false, data: {}, msg: "删除数据不能为空" };
  if (!service) return { ok: false, data: {}, msg: "service不能为空" };
  
  if (Array.isArray(value)) {
    value = value.join(",");
  }
  
  const url = `/${app}/delete/${service}`;
  const req = [
    {
      serviceName: service,
      condition: [{ colName: key, ruleType: "in", value: value }],
    },
  ];
  
  const res = await $http.post(url, req);
  
  if (res?.data?.state === "SUCCESS") {
    return { ok: true, data: res.data.data, msg: "删除成功" };
  } else {
    return { ok: false, data: {}, msg: res?.data?.resultMessage || "删除失败" };
  }
};

📊 标准数据格式

1. 请求格式

标准请求结构

javascript
const request = {
  serviceName: "srvuser_list_select",  // 服务名称
  colNames: ["*"],                      // 查询字段
  condition: [                          // 查询条件
    {
      colName: "status",
      ruleType: "eq",
      value: "active"
    },
    {
      colName: "age",
      ruleType: "gt",
      value: "18"
    }
  ],
  order: [                              // 排序
    {
      colName: "create_time",
      orderType: "DESC"
    }
  ],
  page: {                               // 分页
    pageNo: 1,
    rownumber: 20
  },
  data: [                               // 数据(新增/更新)
    {
      name: "张三",
      age: 25,
      email: "zhangsan@example.com"
    }
  ]
}

条件规则类型 (ruleType)

javascript
// 常用规则类型
eq:     // 等于
ne:     // 不等于
gt:     // 大于
lt:     // 小于
ge:     // 大于等于
le:     // 小于等于
like:   // 模糊查询
in:     // 包含
nin:    // 不包含
between: // 区间
isnull: // 为空
notnull: // 不为空

// 示例
{
  colName: "name",
  ruleType: "like",
  value: "张"  // 匹配包含"张"的姓名
}

2. 响应格式

成功响应

javascript
{
  state: "SUCCESS",           // 状态
  data: [                     // 数据
    {
      id: 1,
      name: "张三",
      age: 25,
      create_time: "2025-12-19 10:00:00"
    }
  ],
  page: {                     // 分页信息
    pageNo: 1,
    rownumber: 20,
    total: 100
  },
  resultMessage: "操作成功",  // 提示信息
  resultCode: "0000"          // 结果码
}

失败响应

javascript
{
  state: "FAILURE",
  data: [],
  resultMessage: "查询失败:数据库连接异常",
  resultCode: "5000"
}

特殊状态码

javascript
"0011"  // 认证失败,需要重新登录
"0000"  // 一般错误,显示提示信息
"9998"  // 静默处理,不显示提示

🔌 核心API接口

1. 页面配置相关

获取页面配置

javascript
// 接口:获取页面基础配置
const pageConfigReq = {
  serviceName: "srvpage_cfg_page_guest_select",
  colNames: [
    "page_title",
    "page_name",
    "id",
    "page_style_no",
    "srv_req_no",
    "preview",
    "page_no",
    "page_options",
    "tmpl_page_no",
    "page_style_json"
  ],
  condition: [
    {
      colName: "page_no",
      ruleType: "eq",
      value: "home_page"  // 页面编号
    }
  ]
}

// 调用
const { data, ok, msg } = await $selectOne(
  "/config/select/srvpage_cfg_page_guest_select",
  pageConfigReq
);

获取页面组件

javascript
// 接口:获取页面所有组件
const componentsReq = {
  serviceName: "srvpage_cfg_page_component_select",
  colNames: ["*"],
  condition: [
    {
      colName: "page_no",
      ruleType: "eq",
      value: "home_page"
    }
  ]
}

// 调用
const { data, ok, msg } = await $selectList(
  "/config/select/srvpage_cfg_page_component_select",
  componentsReq
);

保存页面配置

javascript
// 接口:保存或更新页面
const savePageReq = {
  serviceName: "srvpage_cfg_page_guest_update",
  data: [
    {
      page_no: "home_page",
      page_name: "首页",
      page_title: "系统首页",
      page_style_json: "{\"bgColor\":\"#ffffff\"}"
    }
  ]
}

// 调用
const res = await $http.post(
  "/config/update/srvpage_cfg_page_guest_update",
  savePageReq
);

保存组件配置

javascript
// 接口:保存组件
const saveComponentReq = {
  serviceName: "srvpage_cfg_page_component_add",
  data: [
    {
      page_no: "home_page",
      com_type: "list",
      comp_label: "用户列表",
      com_json: "{\"list_type\":\"table\"}",
      row_json: "{\"interface_json\":{}}"
    }
  ]
}

// 调用
const res = await $http.post(
  "/config/add/srvpage_cfg_page_component_add",
  saveComponentReq
);

2. 业务数据相关

获取业务列表

javascript
// 接口:查询用户列表
const userListReq = {
  serviceName: "srvuser_list_select",
  colNames: ["*", "dept_name", "role_name"],
  condition: [
    {
      colName: "status",
      ruleType: "eq",
      value: "active"
    }
  ],
  order: [
    {
      colName: "create_time",
      orderType: "DESC"
    }
  ],
  page: {
    pageNo: 1,
    rownumber: 20
  }
}

// 调用
const { data, page, ok } = await $selectList(
  "/business/select/srvuser_list_select",
  userListReq
);

// 使用
if (ok) {
  this.tableData = data;
  this.pagination = page;
}

新增业务数据

javascript
// 接口:添加用户
const addUserReq = {
  serviceName: "srvuser_list_add",
  data: [
    {
      name: "李四",
      age: 28,
      email: "lisi@example.com",
      dept_id: "D001"
    }
  ]
}

// 调用
const res = await $http.post(
  "/business/add/srvuser_list_add",
  addUserReq
);

if (res.data.state === "SUCCESS") {
  this.$message.success("添加成功");
}

更新业务数据

javascript
// 接口:更新用户
const updateUserReq = {
  serviceName: "srvuser_list_update",
  condition: [
    {
      colName: "id",
      ruleType: "eq",
      value: "1001"
    }
  ],
  data: [
    {
      name: "张三(已修改)",
      age: 26
    }
  ]
}

// 调用
const res = await $http.post(
  "/business/update/srvuser_list_update",
  updateUserReq
);

删除业务数据

javascript
// 调用快捷方法
const result = await $delete({
  app: "business",
  service: "srvuser_list_delete",
  key: "id",
  value: "1001"  // 支持字符串或数组
});

if (result.ok) {
  this.$message.success(result.msg);
}

3. 流程相关

获取流程列表

javascript
// 接口:待办流程列表
const procListReq = {
  serviceName: "srvproc_instance_select",
  colNames: ["*", "proc_name", "starter_name"],
  condition: [
    {
      colName: "current_handler",
      ruleType: "eq",
      value: currentUser.id
    },
    {
      colName: "status",
      ruleType: "eq",
      value: "pending"
    }
  ],
  page: {
    pageNo: 1,
    rownumber: 20
  }
}

// 调用
const { data, ok } = await $selectList(
  "/process/select/srvproc_instance_select",
  procListReq
);

发起流程

javascript
// 接口:启动流程实例
const startProcReq = {
  serviceName: "srvproc_instance_start",
  data: [
    {
      proc_no: "PROC001",
      biz_no: "BIZ001",
      variables: {
        amount: 5000,
        reason: "采购申请"
      }
    }
  ]
}

// 调用
const res = await $http.post(
  "/process/start/srvproc_instance_start",
  startProcReq
);

审批流程

javascript
// 接口:流程审批
const approveReq = {
  serviceName: "srvproc_instance_approve",
  data: [
    {
      proc_instance_no: "PROC_INST_001",
      action: "approve",  // approve/reject/transfer
      comment: "同意",
      variables: {
        next_approver: "user_002"
      }
    }
  ]
}

// 调用
const res = await $http.post(
  "/process/approve/srvproc_instance_approve",
  approveReq
);

4. 文件上传下载

文件上传

javascript
// 接口:上传文件
const uploadFile = async (file) => {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('serviceName', 'srvfile_upload');
  
  const res = await $http.post(
    '/file/upload/srvfile_upload',
    formData,
    {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    }
  );
  
  if (res.data.state === "SUCCESS") {
    return res.data.data[0].file_no;  // 返回文件编号
  }
};

文件下载

javascript
// 使用封装方法
import { getImagePath, getFilePathByUrl } from "@/common/http";

// 图片预览
const imageUrl = getImagePath(fileNo);  // 返回完整URL

// 文件下载
const fileUrl = getFilePathByUrl(filePath);  // 返回下载URL
window.open(fileUrl);

// 带缩略图的图片
const thumbUrl = getFilePathByUrl(fileNo, true);  // 返回缩略图URL

🎯 高级功能

1. 批量操作

javascript
// 批量删除
const batchDelete = async (selectedIds) => {
  const result = await $delete({
    app: "business",
    service: "srvuser_list_delete",
    key: "id",
    value: selectedIds  // 数组自动转换为逗号分隔
  });
  
  return result;
};

// 批量更新
const batchUpdate = async (ids, updateData) => {
  const req = {
    serviceName: "srvuser_list_batch_update",
    condition: [
      {
        colName: "id",
        ruleType: "in",
        value: ids.join(",")
      }
    ],
    data: [updateData]
  };
  
  return await $http.post("/business/update/srvuser_list_batch_update", req);
};

2. 事务处理

javascript
// 事务性操作(需要后端支持)
const transactionOperation = async () => {
  try {
    // 开启事务
    const beginReq = { serviceName: "srvtransaction_begin" };
    await $http.post("/transaction/begin", beginReq);
    
    // 执行操作1
    await $http.post("/business/add/srvuser_list_add", userData);
    
    // 执行操作2
    await $http.post("/business/add/srvlog_list_add", logData);
    
    // 提交事务
    const commitReq = { serviceName: "srvtransaction_commit" };
    await $http.post("/transaction/commit", commitReq);
    
    this.$message.success("操作成功");
  } catch (error) {
    // 回滚事务
    const rollbackReq = { serviceName: "srvtransaction_rollback" };
    await $http.post("/transaction/rollback", rollbackReq);
    this.$message.error("操作失败,已回滚");
  }
};

3. 数据导出

javascript
// 导出Excel
const exportExcel = async (serviceName, condition) => {
  const req = {
    serviceName: serviceName,
    colNames: ["*"],
    condition: condition,
    export: {
      format: "excel",
      filename: "导出数据.xlsx"
    }
  };
  
  const res = await $http.post(
    "/export/srvdata_export",
    req,
    { responseType: "blob" }  // 重要:指定响应类型为二进制
  );
  
  // 下载文件
  const url = window.URL.createObjectURL(new Blob([res.data]));
  const link = document.createElement('a');
  link.href = url;
  link.download = "导出数据.xlsx";
  link.click();
};

4. 实时数据(WebSocket)

javascript
// WebSocket连接(如果需要)
class WebSocketManager {
  constructor() {
    this.ws = null;
    this.reconnectTimer = null;
  }
  
  connect() {
    const ticket = sessionStorage.getItem("bx_auth_ticket");
    const wsUrl = `ws://your-domain.com/ws?ticket=${ticket}`;
    
    this.ws = new WebSocket(wsUrl);
    
    this.ws.onopen = () => {
      console.log("WebSocket连接成功");
      this.heartbeat();  // 开始心跳
    };
    
    this.ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      this.handleMessage(data);
    };
    
    this.ws.onclose = () => {
      console.log("WebSocket连接断开");
      this.reconnect();  // 重连
    };
  }
  
  handleMessage(data) {
    // 处理实时消息
    switch (data.type) {
      case "notify":
        this.showNotification(data.content);
        break;
      case "update":
        this.refreshData(data.service);
        break;
    }
  }
  
  // 发送消息
  send(data) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(data));
    }
  }
  
  // 心跳
  heartbeat() {
    setInterval(() => {
      this.send({ type: "ping" });
    }, 30000);  // 30秒一次
  }
  
  reconnect() {
    if (this.reconnectTimer) return;
    this.reconnectTimer = setTimeout(() => {
      this.reconnectTimer = null;
      this.connect();
    }, 5000);
  }
}

// 使用
const wsManager = new WebSocketManager();
wsManager.connect();

// 发送消息
wsManager.send({
  type: "notify",
  target: "user_001",
  content: "您有新的待办"
});

🔒 认证与权限

1. 认证流程

javascript
// 认证票据管理
const AuthManager = {
  // 获取票据
  getTicket() {
    return sessionStorage.getItem("bx_auth_ticket");
  },
  
  // 设置票据
  setTicket(ticket) {
    sessionStorage.setItem("bx_auth_ticket", ticket);
  },
  
  // 清除票据
  clearTicket() {
    sessionStorage.removeItem("bx_auth_ticket");
    sessionStorage.removeItem("current_login_user");
  },
  
  // 检查登录状态
  isLoggedIn() {
    return !!this.getTicket();
  },
  
  // 登录
  async login(username, password) {
    const res = await $http.post("/auth/login", {
      username,
      password
    });
    
    if (res.data.state === "SUCCESS") {
      const ticket = res.data.data.ticket;
      const userInfo = res.data.data.user;
      
      this.setTicket(ticket);
      sessionStorage.setItem("current_login_user", JSON.stringify(userInfo));
      
      return { ok: true, user: userInfo };
    }
    
    return { ok: false, msg: res.data.resultMessage };
  },
  
  // 退出
  logout() {
    this.clearTicket();
    window.location.href = "/login";
  }
};

2. 权限检查

javascript
// 权限检查工具
const PermissionManager = {
  // 获取用户权限列表
  getPermissions() {
    const user = sessionStorage.getItem("current_login_user");
    if (!user) return [];
    return JSON.parse(user).permissions || [];
  },
  
  // 检查单个权限
  hasPermission(permission) {
    const perms = this.getPermissions();
    return perms.includes(permission);
  },
  
  // 检查多个权限(任意一个)
  hasAnyPermission(...permissions) {
    const perms = this.getPermissions();
    return permissions.some(p => perms.includes(p));
  },
  
  // 检查多个权限(全部)
  hasAllPermissions(...permissions) {
    const perms = this.getPermissions();
    return permissions.every(p => perms.includes(p));
  },
  
  // 按钮级权限控制
  checkButtonPermission(permission, element) {
    if (!this.hasPermission(permission)) {
      element.style.display = "none";
    }
  }
};

// Vue指令方式
Vue.directive('permission', {
  inserted: function (el, binding) {
    const permission = binding.value;
    if (!PermissionManager.hasPermission(permission)) {
      el.parentNode && el.parentNode.removeChild(el);
    }
  }
});

// 使用
<button v-permission="'user:add'">添加用户</button>

📊 数据格式转换

1. 请求转换器

javascript
// 标准化请求数据
function normalizeRequest(serviceName, data, options = {}) {
  const {
    condition = [],
    page = { pageNo: 1, rownumber: 20 },
    order = [],
    colNames = ["*"]
  } = options;
  
  return {
    serviceName,
    colNames,
    condition,
    order,
    page,
    data: Array.isArray(data) ? data : [data]
  };
}

// 使用
const req = normalizeRequest(
  "srvuser_list_select",
  null,
  {
    condition: [{ colName: "status", ruleType: "eq", value: "active" }],
    page: { pageNo: 1, rownumber: 10 }
  }
);

2. 响应转换器

javascript
// 标准化响应数据
function normalizeResponse(response) {
  if (!response || response.state !== "SUCCESS") {
    return {
      success: false,
      data: [],
      message: response?.resultMessage || "请求失败",
      code: response?.resultCode || "UNKNOWN"
    };
  }
  
  return {
    success: true,
    data: response.data || [],
    page: response.page,
    message: response.resultMessage || "操作成功",
    code: response.resultCode || "0000"
  };
}

// 使用
const res = await $http.post(url, req);
const normalized = normalizeResponse(res.data);

if (normalized.success) {
  this.tableData = normalized.data;
  this.pagination = normalized.page;
}

🔍 调试与监控

1. 请求日志

javascript
// 请求拦截器中添加日志
instance.interceptors.request.use(config => {
  const start = Date.now();
  
  // 保存到config,用于响应拦截器计算耗时
  config.metadata = { startTime: start };
  
  console.log(`[API] ${config.method?.toUpperCase()} ${config.url}`, {
    params: config.params,
    data: config.data,
    headers: config.headers
  });
  
  return config;
});

instance.interceptors.response.use(response => {
  const duration = Date.now() - response.config.metadata.startTime;
  
  console.log(`[API] ${response.status} ${response.config.url} (${duration}ms)`, {
    data: response.data
  });
  
  return response;
});

2. 性能监控

javascript
// API响应时间监控
const apiMetrics = {
  requests: [],
  
  record(url, duration, success) {
    this.requests.push({ url, duration, success, timestamp: Date.now() });
    
    // 只保留最近100条记录
    if (this.requests.length > 100) {
      this.requests.shift();
    }
  },
  
  getSlowRequests(threshold = 1000) {
    return this.requests.filter(r => r.duration > threshold);
  },
  
  getSuccessRate() {
    const total = this.requests.length;
    const success = this.requests.filter(r => r.success).length;
    return total > 0 ? (success / total * 100).toFixed(2) : 100;
  },
  
  clear() {
    this.requests = [];
  }
};

// 在拦截器中使用
instance.interceptors.response.use(
  response => {
    const duration = Date.now() - response.config.metadata.startTime;
    apiMetrics.record(response.config.url, duration, true);
    return response;
  },
  error => {
    if (error.config) {
      const duration = Date.now() - error.config.metadata.startTime;
      apiMetrics.record(error.config.url, duration, false);
    }
    return Promise.reject(error);
  }
);

🛠️ 实用工具函数

1. 请求包装器

javascript
// 带重试机制的请求
async function requestWithRetry(url, req, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const res = await $http.post(url, req);
      return res;
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
    }
  }
}

// 带超时控制的请求
async function requestWithTimeout(url, req, timeout = 30000) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);
  
  try {
    const res = await $http.post(url, req, {
      signal: controller.signal
    });
    clearTimeout(timeoutId);
    return res;
  } catch (error) {
    if (error.name === 'AbortError') {
      throw new Error('请求超时');
    }
    throw error;
  }
}

2. 批量请求

javascript
// 批量并发请求
async function batchRequest(requests, concurrency = 5) {
  const results = [];
  const executing = [];
  
  for (let i = 0; i < requests.length; i++) {
    const promise = requests[i]().then(result => {
      results[i] = result;
      executing.splice(executing.indexOf(promise), 1);
    });
    
    executing.push(promise);
    
    if (executing.length >= concurrency) {
      await Promise.race(executing);
    }
  }
  
  await Promise.all(executing);
  return results;
}

// 使用示例
const requests = [
  () => $http.post('/api/data1', req1),
  () => $http.post('/api/data2', req2),
  () => $http.post('/api/data3', req3)
];

const results = await batchRequest(requests);

文档维护: l-pc-front 开发组
最后更新: 2025-12-19

最近更新