作为企业内部应用开发的热门平台,钉钉小程序在实际落地时经常面临一个关键问题:如何同时适配移动端和PC端的不同使用场景?最近我在开发一个内部审批系统时,就遇到了这个典型挑战。经过多次尝试和调整,最终采用了"一套业务逻辑,两套前端实现"的解决方案。下面分享具体实现过程和踩坑经验。
我们需要开发一个请假审批系统,要求:
这种需求在OA类应用中非常典型——员工在外用手机提交申请,主管在办公室用电脑审批。看似简单的需求,在钉钉生态中却存在一些特殊的适配问题。
在钉钉开发者后台(https://open.dingtalk.com)创建应用时,有几个关键选择需要注意:
重要提示:如果漏选小程序能力,后续将无法正确配置跨端访问行为。这是我们第一个版本遇到的坑——当时只勾选了H5微应用,导致PC端访问异常。
钉钉后台的"开发管理"页面有几个影响PC端访问的关键配置项:
是否支持PC端:这个选项控制着工作台搜索结果的跳转行为
PC端应用地址:必须填写完整的HTTP/HTTPS地址
https://your-domain.com/pc-entry通过多次测试,我们记录了各种配置组合下的实际表现:
| 配置组合 | 工作台搜索打开 | 最近使用打开 | 现象分析 |
|---|---|---|---|
| 支持PC+填写地址 | 钉钉内小程序 | 浏览器打开PC地址 | 预期行为 |
| 支持PC+空地址 | 跳转钉钉官网 | 钉钉内小程序 | 危险配置 |
| 不支持PC | 钉钉内小程序 | 钉钉内小程序 | 纯移动方案 |
最危险的是第二种情况——当勾选支持PC但未填写地址时:
我们最终采用的方案架构如下:
code复制[后端API服务]
↑ ↑
[钉钉小程序] [PC端Web应用]
javascript复制// 小程序端认证
dd.getAuthCode({
success: (res) => {
const code = res.authCode;
// 用code换取用户身份
}
});
// PC端认证(OAuth2.0授权码模式)
window.location.href = `https://oapi.dingtalk.com/connect/oauth2/sns_authorize?
appid=${appId}&
response_type=code&
scope=snsapi_auth&
state=STATE&
redirect_uri=${encodeURIComponent(redirectUri)}`;
由于两套前端代码,我们建立了统一的样式规范:
css复制:root {
--primary-color: #1890ff;
--success-color: #52c41a;
}
scss复制$spacer: 4px;
@function space($multiplier) {
@return $spacer * $multiplier;
}
问题现象:
解决方案:
问题现象:
解决方案:
javascript复制// API客户端封装
const baseURL = process.env.NODE_ENV === 'development'
? 'http://localhost:8080/api'
: 'https://api.your-domain.com';
const request = (url, options) => {
return fetch(`${baseURL}${url}`, options);
};
json复制{
"subPackages": [{
"root": "subpackageA",
"pages": ["pages/subA/index"]
}]
}
javascript复制Page({
onLoad() {
this.preloadData();
},
preloadData() {
// 提前加载下一页数据
}
});
javascript复制const cache = new Map();
const cachedRequest = async (url) => {
if (cache.has(url)) {
return cache.get(url);
}
const data = await request(url);
cache.set(url, data);
return data;
};
vue复制<template>
<el-table
:data="tableData"
height="500"
row-key="id"
:row-height="60">
</el-table>
</template>
采用Docker容器化部署:
dockerfile复制FROM nginx:alpine
COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
Nginx配置关键点:
nginx复制location / {
try_files $uri $uri/ /index.html;
gzip on;
}
javascript复制App({
onError(err) {
dd.httpRequest({
url: '/log/error',
data: { error: err.stack }
});
}
});
javascript复制import { init } from '@aliyun-sls/web-rum';
init({
pid: 'your-project-id',
page: 'your-page'
});
使用ELK栈:
关键日志字段:
code复制timestamp, userId, deviceType, apiPath, responseTime, statusCode
经过这个项目的实践,有几个关键经验值得分享:
实际开发中,我们还发现钉钉在不同客户端的一些细微差异:
这些经验让我们在后续项目中节省了大量调试时间。对于需要跨端支持的企业应用,这种"一套业务两套前端"的架构虽然初期投入较大,但长期来看更利于各端的体验优化和独立迭代。