案例说明
本案例介绍APP微应用插件是如何开发的,上方区域展示地图,点击查看列表页面展示图二;点击请假表单页面或者地图marker进入图三。
案例效果如下:
图一:
图二:
图三:
开发步骤
1. 项目下载
Gitee仓库下载
git clone https://gitee.com/ketr/jecloud-app-archetype
2.修改项目名称
例如:jecloud-app-demo
命名规则:微应用的访问地址和部署目录是以项目最后一个单词(demo)命名, 可以根据业务需要自行修改
3.准备开发环境
node:v 14.18.3
npm:v 6.14.15
4. 安装依赖
npm run setup:lib
在这个脚手架中没有安装app-func(功能解析)的依赖,如果业务组件中用到该依赖的相关东西,需要以下步骤:
1.安装 @jecloud/app-func
执行命令:npm i @jecloud/app-func
进行安装
2.在src/app/index.js 引入@jecloud/app-func
并注册
// src/app/index.js 代码参考如下:
// 引入功能包
import func from '@jecloud/app-func';
export default {
/**
* 可以添加一些自定义依赖
* @param {*} param0
*/
onAppInit: function (app) {
// 安装功能对象
app.use(func);
func.setup();
console.log('App Init', app);
},
onLaunch: function () {
console.log('App Launch');
},
onShow: function () {
console.log('App Show');
},
onHide: function () {
console.log('App Hide');
},
};
5. 配置开发环境
新建项目配置文件 .env.development.local,配置系统的代理地址,参考如下:
# 代理服务地址
VUE_APP_SERVICE_PROXY = https://example.jecloud.net
# 代理websocket服务地址
VUE_APP_WEBSOCKET_PROXY = wss://example.jecloud.net
6.启动项目
npm run dev
开发项目(源码案例附在文档后,如有需要,请前往参考~)
1.根目录/src/pages下新建demo文件夹及其相关文件。
2.index.vue 入口文件(地图列表)
核心方法:配置mapinitConfigMap()、 初始化地图initMap()、添加inintMarker()、点击查看列表onMarkerClick()
3.demo.js ajax请求,返回数据
4.urls.js 统一存放ajax请求的url地址
5.form.vue 表单页面
核心方法:加载onLoad()、返回onBackPress()
6.配置pages.json路由文件
7.打包项目
npm run build
在根目录下生成dist文件
8.部署项目
1.找到微应用部署目录:服务器/data/application/openresty/ nginx/jecloud/app/micro,新建 demo 微应用目录:demo。
2.将 dist/build/h5 目录里的文件(不包含 h5 文件夹),上传到服务器 的 demo 目录下
浏览器输入微应用模块地址 http://服务器地址/app/micro/demo,如果可 以访问成功,代表部署成功。
9. 平台配置
1.微应用管理配置
2.添加菜单插件(其中功能插件及其菜单的权限都是跟随PC系统)
10.预览应用
1 浏览器输入地址: 域名/app#/?appId=自己的AppID
例如: https://example.jecloud.net/app#/?appId=2023-0920-1407-4526
2 扫码看效果
核心代码
- index.vue
<template>
<app-config-provider>
<view class="outer-app-demo-plugin">
<view class="inner-app-demo-plugin">
<!-- <uni-card title="地图"> -->
<div ref="mapRef" class="map" style="width: 100%; height: 450px"></div>
<!-- </uni-card> -->
<button class="button-view" type="primary" @click="onMarkerClick"> 查看列表页面 </button>
<button class="button-view" type="primary" @click="goFunForm()"> 请假表单页面 </button>
</view>
</view>
</app-config-provider>
</template>
<script>
import { onMounted, reactive, defineComponent, onBeforeMount, toRefs, watch, h } from 'vue';
import AMapLoader from '@amap/amap-jsapi-loader';
import { getFuncDataList } from './api/demo.js';
import { onShow } from '@dcloudio/uni-app';
// import { Modal } from '@jecloud/utils';
import { showSelectWindow } from '@jecloud/app-func';
export default defineComponent({
name: 'Maps',
components: {},
setup() {
const option = reactive({
lng: 116.404,
lat: 39.915,
AMap: null,
mapRef: null,
mapData: null,
data: [],
markers: [],
});
const methods = {
// 配置map
initConfigMap() {
AMapLoader.load({
key: '651bbe1427b37c74deea8541a643918a', // 申请好的Web端开发者Key,首次调用 load 时必填
plugins: [
'AMap.Scale',
'AMap.ToolBar',
'AMap.PlaceSearch',
'AMap.Geolocation',
'AMap.Geocoder',
'AMap.Autocomplete',
'AMap.OverView',
'AMap.MapType',
'AMap.PolyEditor',
'AMap.CircleEditor',
'AMap.DistrictSearch',
'AMap.CircleMarker',
'AMap.Polyline',
'AMap.Pixel',
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
version: '1.1',
plugins: ['overlay/SimpleMarker', 'geo/DistrictExplorer'],
},
}).then((map) => {
option.AMap = map;
option.mapData = methods.initMap(map);
return option.mapData;
});
},
// 初始化地图
initMap(AMap) {
const mapData = new AMap.Map(option.mapRef, {
mapStyle: 'amap://styles/98b26d04358dd80ee479ca1dfe9edd06', // 配置的地图样式
zoom: 5,
zooms: [1, 20],
center: [116.404, 39.915],
features: ['road', 'bg', 'point', 'building'], // 支持'bg'(地图背景)、'point'(POI点)、'road'(道路)、'building'(建筑物)
resizeEnable: true, // 监控地图容器尺寸变化,默认值为false
expandZoomRange: true, // 支持可以扩展最大缩放级别,和zooms属性配合使用,设置为true的时候,zooms的最大级别在PC上可以扩大到20级
});
mapData.on('click', (e) => {
console.log(e);
});
return mapData;
},
getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
},
// Marker
inintMarker(item, index) {
const marker = new option.AMap.Marker({
map: option.mapData,
icon: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png',
position: [option.lng + 0.01 * index, option.lat + 0.01 * index],
offset: new option.AMap.Pixel(
methods.getRandom(-200, 200),
methods.getRandom(-100, 100),
),
id: item.HR_QJSQ_ID,
content: `<div style="background: yellow;border-radius: 50%;width: 40px;height: 40px;text-align: center;line-height: 40px">${
index + 1
}</div>`,
});
marker.content = item.HR_QJSQ_ID;
// 点击事件
marker.on('click', (e) => {
methods.goFunForm(e.target.content);
});
return marker;
},
// 进入表单
goFunForm(id) {
uni.navigateTo({
url: id ? `/pages/demo/form?id=${id}` : '/pages/demo/form',
});
},
// 获取列表数据
getFuncData() {
const params = {
tableCode: 'HR_QJSQ',
funcCode: 'HR_QJSQ',
};
getFuncDataList(params).then((data) => {
option.data = data.rows;
});
},
// 点击查看列表
onMarkerClick() {
showSelectWindow({
configInfo: 'HR_QJSQ,grid,HR_QJSQ_ID',
type: 'grid',
value: '',
callback: ({ rows }) => {
if (rows && rows[0].HR_QJSQ_ID) {
methods.goFunForm(rows[0].HR_QJSQ_ID);
}
},
});
},
};
watch(
() => [option.AMap, option.data],
(val, value1) => {
if (!(option.AMap && value1.length)) {
return false;
}
// 清除标记点
option.mapData.remove(option.markers);
option.markers = [];
// 渲染标记点
option.data.map((item, index) => {
const marker = methods.inintMarker(item, index);
option.markers.push(marker);
});
},
{ deep: true },
);
onBeforeMount(() => {});
onMounted(() => {
// 初始地图
methods.initConfigMap();
// 获取列表数据
methods.getFuncData();
});
onShow(() => {
uni.$on('updateData', () => {
methods.getFuncData();
});
});
return { ...toRefs(option), ...methods };
},
});
</script>
<style lang="scss" scoped>
.outer-app-demo-plugin {
width: 100%;
height: calc(100vh - var(--window-top)) !important;
.inner-app-demo-plugin {
width: 100%;
height: 100%;
overflow: auto;
}
.button-view {
width: 60%;
margin-top: 30px;
}
.func-height {
height: 600px;
}
}
</style>
- form.vue
<template>
<app-config-provider>
<view class="outer-app-demo-form">
<je-func
class="func-height"
:readonly="isReadonly"
func-code="HR_QJSQ"
is-func-form
:bean-id="beanId"
/>
</view>
</app-config-provider>
</template>
<script>
import { onMounted, defineComponent, onBeforeMount, reactive, toRefs } from 'vue';
import { onLoad, onBackPress } from '@dcloudio/uni-app';
export default defineComponent({
name: 'Maps',
components: {},
setup() {
const state = reactive({ beanId: '', isReadonly: false });
onBeforeMount(() => {});
onMounted(() => {});
// 加载
onLoad((e) => {
state.beanId = e.id || '';
state.isReadonly = e.id;
});
// 返回
onBackPress((e) => {
if (e.from == 'backbutton') {
uni.$emit('updateData');
uni.navigateBack({
delta: 1, //返回:
});
return true;
}
});
return { ...toRefs(state) };
},
});
</script>
<style lang="scss" scoped>
.outer-app-demo-form {
width: 100%;
height: calc(100vh - var(--window-top)) !important;
}
</style>
- pages.json增加下面内容
{"path": "pages/demo/index",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "培训案例"
}
},
{"path": "pages/demo/form",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "表单详情"
}
},