## 使用package.json内的脚本 'npm run commit' 提交代码 ## 使用package.json内的脚本 'npm run commit' 提交代码 ## 使用package.json内的脚本 'npm run commit' 提交代码 ## 全局状态存储中以 map 为前缀的state状态都是用于数据检索用的 不建议用于页面展示 # 导视开发提测流程(使用npm包管理工具,其他类似) 1. 修改项目中根目录下的`.drone.yml`文件和`.tpl`文件中的**svn地址**配置,如下所示: ```yml # 在.drone.yml文件的第75行, 修改svndir变量的值为相应项目的svn地址 # svn目录定义 开头和结尾不能有/,且不能出现中文乱码,复制地址时建议只复制02项目定制后的目录,会影响到变量取值 - svndir="2022研发/Prd007_智能导视/02项目定制" # 以上海浦项写字楼项目为例,如下所示: - svndir="2022研发/Prd007_智能导视/02项目定制/SH013上海浦项写字楼/导视应用" ``` ```tpl 项目svn地址:http://svn.1000my.com/svn/2022研发/Prd007_智能导视/02项目定制/ 项目svn地址:http://svn.1000my.com/svn/2022研发/Prd007_智能导视/02项目定制/SH013上海浦项写字楼/导视应用/ ``` 2. 修改项目中根目录下的`.tpl`文件中的**git地址**配置,如下所示: ```tpl 项目git地址:https://git.1000my.com/ 项目git地址:https://git.1000my.com/project_shpuxiang/shpuxiang_daoshi_vue ``` 3. 钉钉**群机器人**配置([钉钉机器人接入官方文档](https://open.dingtalk.com/document/group/custom-robot-access)) * 在项目钉钉群界面点击右上角的**群设置**按钮。 * 在群设置界面点击**智能群助手**按钮。 * 在智能群助手界面点击**添加机器人**按钮。 * 在弹出的弹窗界面中点击添加机器人右边的**小齿轮**按钮。 * 在选择添加机器人列表中选择**自定义机器人**。 * 在机器人详情界面点击**添加**按钮。 * 在添加机器人界面可以修改机器人的**头像**以及**名字**,在**安全设置**选项中选择**自定义关键字**,并添加**地址**关键字,勾选**我已阅读并同意《自定义机器人服务及免责条款**》,然后点击**完成**按钮。 * 完成创建后会自动生成机器人的**Webhook**地址,例如:`https://oapi.dingtalk.com/robot/send?access_token=XXXXXX`。复制地址中的`access_token=`后面的值,修改项目中根目录下的`.drone.yml`文件中的**钉钉机器人token**配置,如下所示: ```yml # 钉钉机器人token配置在.drone.yml文件的第112行 # 钉钉通知 - name: dingTalk notification pull: if-not-exists image: lddsb/drone-dingtalk-message failure: ignore settings: token: 5f1337cd8cb70e007d2693f70a3ca89fdec543781a9a9fe2f5519e061a1820a8 ``` 4. 项目首次提测步骤:(由于项目是从脚手架派生出来,log文件里会有脚手架的相关信息,所以第一次须删除相关内容) * 删除项目根目录下的`CHANGELOG.md`文件。 * 通过`npm run commit`命令提交本地代码。 * 通过`npm run release:first`命令生成首次提测的`CHANGELOG.md`文件,该命令也会把生成的**tag**提交到远程仓库,相当于也执行了`push`命令。 * 在仓库项目地址中把`dev`分支合并到`test`分支,合并分支时选择**变基并合并** 5. 项目后续每次提测步骤: * 通过`npm run commit`命令提交本地代码。 * 通过`npm run release`命令生成`CHANGELOG.md`文件,该命令也会把生成的**tag**提交到远程仓库,相当于也执行了`push`命令。 * 在仓库项目地址中把`dev`分支合并到`test`分支,合并分支时选择**变基并合并** 6. 每次当测试通过,项目正式发包后: * 通过`npm run changelog`命令生成发包后的`CHANGELOG.md`文件,该命令也会把生成的**tag**提交到远程仓库,相当于也执行了`push`命令。 ### 1. web页面fork **common** 组织下的相应仓库并设置具体见文档 2. `git clone` 到本地 3. 配置 mac和linux下 `chmod 700 .husky/*` 4. 推荐通过npx创建项目 `npx @vue/cli create project_name_` 5. 建议安装vscode的vue3的专属插件volar 6. Vue3常用工具库函数[VueUse](https://vueuse.org/) 7. 开发 及内置组件使用说明见以下文档 8. 所有需要写在App.vue内的组件请放到PublicComponent组件 9. windows平台退出弹框点击区域为左上角200*200的矩形 内部会判断手指点击坐标是否在安全区域内 内嵌Android自行删除相关业务代码 10. 地图SDK地址:https://1000my.com/mapapidoc/index.html 11. **所有跳到导航页面之前请先调用 @/utils/Class/Brand.ts 来生成一个新的shop数据 以更新store内的shop数据 (本身操作是店铺除外)看以下demo** 12. ```javascript import { useStore } from '@/store/root' import Brand from '@/utils/Class/Brand' import { useRouter } from 'vue-router' export const useFacilityNav = () => { const store = useStore() const router = useRouter() // eslint-disable-next-line max-params function _handleFacility(name: string, floorOrder: number, floorName: string, logoPath: string, yaxis: number) { const shop = new Brand({ shopName: name, floorOrder, floor: floorName, logoUrl: logoPath, yaxis }) store.SET_SHOP(shop) } function handleFacility(item: Facility) { const facility = window.Map_QM.pathIcon({ type: item.abbreviation }) const floorName = store.currentBuildingFloorsList.find(floor => floor.floorOrder === facility.floor)?.floor _handleFacility(item.customFacilityName, facility.floor, floorName as string, item.filePath, facility.node as any) router.push('/nav') } return { handleFacility } } ``` # 无需引入全局mixin.scss文件 (已提前引入) ```javascript // vue.config.js module.exports = defineConfig({ css: { loaderOptions: { scss: { additionalData: `@import "@/assets/scss/mixin.scss";` } } }, lintOnSave: true, productionSourceMap: false }) ``` ### 添加基础旋转动画(scss) 以及列表过渡动画 ```scss // @/assets/scss/mixin.scss @mixin no-wrap { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } @mixin more-wrap($row: 2) { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: $row; -webkit-box-orient: vertical; } @mixin rotate($turn: 360deg, $count: infinite) { animation-name: rotate; animation-duration: 2s; animation-iteration-count: $count; animation-timing-function: linear; @keyframes rotate { 0% { transform: rotate(0) translateZ(0); } 100% { transform: rotate($turn) translateZ(0); } } } // App.vue .zoom-enter-active { transition: all 0.3s; transition-timing-function: cubic-bezier(0.75, 0, 0.24, 1); } .zoom-leave-active { position: absolute !important; transition: all 0.3s; transition-timing-function: cubic-bezier(0.75, 0, 0.24, 1); } .zoom-enter-from, .zoom-leave-to { transform: scale(0.83); transform-origin: center center; opacity: 0; } .zoom-move { transition: transform 0.3s !important; transition-timing-function: cubic-bezier(0.75, 0, 0.24, 1); } ``` # 组件使用 ### AutoBackNotification | props | type | desc | default | | :---: | :----: | :----------: | :-----: | | title | string | 提示文字 | '' | | delay | number | 倒计时的数字 | 0 | ### Logout | props | type | desc | default | | :--------: | :-----: | :--------------: | :-----: | | modelValue | boolean | 控制组件显示隐藏 | false | | events | type | desc | | :----: | :------: | :----------------: | | bingo | function | 密码输入正确时触发 | ```javascript import { ref } from 'vue' const logoutRef = ref(false) ``` ### Marquees | props | type | desc | default | | :-----: | :----: | :---------------------: | :-----: | | content | string | 滚动的内容 | '' | | delay | number | 第一次滚动时的延迟 时间 | 0.8 | | speed | number | 滚动速度 | 40 | ### Message 使用时引入Message.js ```javascript import Message from '@/base/Message/Message.js' Message({type: 'success', text: '这是一条提示'}) ``` | props | type | desc | default | | :---: | :----: | :----------------------------------------------------------: | :-----: | | type | string | warn \| error\| success(由于UI的不确定性 目前建议只使用success类型) | success | | text | string | 提示文字 | '' | ### Icon 以下为Icon组件通用props | props | type | desc | default | | :---: | :----: | :------: | :-----: | | size | number | 尺寸大小 | 35 | | fill | string | 填充颜色 | #515151 | ### ScrollView | props | type | desc | default | | :-------------: | :-------------: | :----------------------------------------------------------: | :-----: | | list | array \| string | 监听的数据源 当数据源改动时会自动调用refresh重新计算滚动高度 | - | | scrollbar | boolean | 显示滚动条 | false | | scrollX | boolean | 是否需要横向滚动 | false | | refreshDelay | number | 延迟初始化实例的时间 | 20 | | scrollTop | boolean | 当list数据改变时是否自动回到顶部或者左边(scrollX为true时) | true | | deceleration | number | 表示 momentum 动画的减速度。 (值越小 滑动之后惯性越大) | 0.02 | | useTransition | boolean | 是否使用 CSS3 transition 动画。如果设置为 false,则使用 requestAnimationFrame 做动画。 | false | | observeImage | boolean | 是否监听图片(有瀑布流布局的地方建议开启) | false | | stopPropagation | boolean | 是否阻止事件冒泡。多用在嵌套 scroll 的场景。 | false | ### EffectFade | props | type | desc | default | | :--------: | :-----: | :----------------: | :-----: | | list | array | 内部渲染需要的数据 | [] | | pagination | boolean | 是否开启提示点 | false | **此组件只初始化swiper透明轮播等相关逻辑 只做展示 dom节点自行实现 通过作用域插槽可拿到循环的每一项数据 作用域插槽字段: `{ item }`** ```javascript ``` ### Map | events | type | desc | | :-----------: | :------: | :----------------------: | | handle-GO | function | 点击地图弹框导航按钮触发 | | handle-Detail | function | 点击地图弹框详情按钮触发 | ### Written(手写组件的父元素需指定宽高) | props | type | desc | default | | :-------------: | :----: | :-----------------------------------: | :-------------------: | | backgroundColor | string | canvas 背景色 | #f2f2f2 | | borderRadius | string | canvas的圆角 | 10px | | fillText | string | canvas绘制区域的提示文字 | 手写区域 | | fillFontSize | string | canvas绘制区域的提示文字大小 | 100px | | fillStyle | string | canvas绘制区域的提示文字颜色 | rgba(85, 73, 54, 0.1) | | lang | string | CN \| EN 指定接口返回的是字母还是汉字 | CN | | strokeStyle | string | 笔触的颜色 | #000 | | events | type | desc | callback params | | :----: | :------: | :------------------------------: | :----------------------------: | | result | function | 组件内部响应式变量list变化时触发 | 接口请求成功之后返回的汉字列表 | ### PlateInput | props | type | desc | default | | :----------: | :------------: | :----------------------------------------------------------: | :-----: | | List | array | 车牌号或者车位号 | [] | | needsEnergy | boolean | 是否需要能源输入框即最后一位的输入 如果切换到车位 可以设置为false | true | | searchMethod | '车牌'\|'车位' | 找车方式 | '车牌' | | events | type | desc | | :-----------: | :------: | :----------------------------------------------------------: | | handle-energy | function | 如needsEnergy为true 则会在初始化自动触发一次此事件 后续需要点击输入框能源车牌输入框 即最后一个输入框 参数为_isEnergy | | confirm | function | 确认找车 即点击找车按钮触发 | **车牌输入框组件现在接受一个slot插槽 可以用来点击时显示loading提示或其他内容** ### PlateKeyboard | props | type | desc | default | | :-----------: | :----: | :--------------------------: | :-----: | | searchMethods | string | 找车方式 ['车牌', '车位'] | '车牌' | | events | type | desc | | :-------------: | :------: | :------------------------------------------------------: | | handle-keyboard | function | 点击找车键盘 参数为点击时的文字 如果为del则会触发del事件 | | del | function | 删除 | **注:PlateInput PlateKeyboard组件默认在Parking.vue引用 寻车逻辑默认写好 需自行到两个组件内部修改UI对应设计稿** # composition hooks 使用 ### 活动导航 ```javascript //活动类型导航 //类型声明:useActivityNav: () => ({ // nav: (activity: Activity) => void; //}) const { nav } = useActivityNav() //nav接受参数类型 ``` ### 导航页面 ```javascript /* replay:重播 pause:暂停 speedUp:加速 handleReplay:设置重播 togglePause: 设置暂停 handleSpeedUp: 设置加速 resetPause: 暂停初始化 */ const { replay, pause, speedUp, handleReplay, togglePause, handleSpeedUp, resetPause } = useMapNavControl() /* directionInfo: 方向信息 pathShopList: 经过店铺 */ const { directionInfo, pathShopList, backPathArray } = useStartNavi(shop, currentFloor, resetPause) /* methodsList: 路线列表 视图层绑定 methodIdx: 路线选中索引 handleControl:路线选择 selectedWayMethod:此函数大多数情况无需调用 只需调用handleControl即可 */ const { methodsList, methodIdx, handleControl, selectedWayMethods } = useChangeNavMethod(backPathArray) /* cameraViews: 文字及提示icon信息 {text: string, image: string} setCameraViews: 设置2d 3d */ const { cameraViews, setCameraViews } = useSetCameraViews(resetPause) ``` ​ ### useQRCode.js (生成二维码) ```javascript /* text: 二维码地址 options: qrcode可选项 详见qrcode第三方库 */ const url = ref('') const { qr } = useQRCode(url, options) ``` ### useFacilityNav.js (公共设施导航) ```javascript const {handleFacility} = useFacilityNav() ``` ### useDay.js (日期) ```javascript import {useDay} from '@/composables/useDay' import {formatDay} from '@/utils/utils' //dateRef:Date实例 //whichWeekRef: 日期 周几 const {dateRef, whichWeekRef} = useDay() //formatDay(Date, y.m.d | y/m/d | y-m-d):string const ymd = formatDay(dateRef.value) ``` ### useTime.js (时间) ```javascript import {useTime} from '@/composables/useTime' const {currentTime} = useTime() ``` ### useWeather.js(天气) ```javascript

{{iconRef.status}}

//天气状况

{{iconRef.icon}}

//天气的iconfont import {useWeather} from '@/composables/useWeather' const {weatherRef, iconRef} = useWeather() ``` ### useSearchShop.js ```javascript import {ref} from 'vue' import {useSearchShopByKeyboard} from '@/composables/useSearchShopByKeyboard' const searchNameRef = ref('') const searchType = 0 //0:键盘搜索 1:手写搜索 //筛选之后的店铺列表 const {searchShopListRef} =useSearchShopByKeyboard(searchNameRef,searchType) ``` ### useGuideMapOperation.js(地图导览模块用于 复位 我的方向) ```javascript // type Item = { // name: String, // nameEn: String, // icon: String, // iconActive: String //选中的图标 // } //switchFloor:(floorOrder:number) => void 楼层切换 需传入楼层 //handleMapIcon:(item:Item, index:number) => void 绑定视图层 //list:Item[] 我的方向 复位 的列表 const { switchFloor, handleMapIcon, list } = useGuideMapOperation() ``` ### useStatistics.js (数据统计) ```javascript useStatistics(data) //data参数详见ts类型声明 ``` ### 切换语言 ```jsx

{{switchLanguage(state.item, 'name')}}
import {reactive} from 'vue' import { useSwitchLanguage } from '@/composables/useSwitchLanguage' const state = reactive({ item: { name: 'zh', nameEn: 'en' } }) const { switchLanguage } = useSwitchLanguage() //如果有多个地方需要用到同个内容 推荐computed包裹避免反复计算 const shopName = computed(() => switchLanguage(shop.value, 'shopName')) ``` # 地图初始化 ```javascript import {onMounted} from 'vue' import {useInitMap,hideMapDialog} from '@/composables/useInitMap' onMounted(() => { useInitMap() }) //该文件暴露除了地图初始化函数 还有一个隐藏地图弹框的函数 hideMapDialog() ``` # 项目内使用的工具函数 ```javascript import { randomNumber, //两个数字之间的随机数 checkPhoneNumber, // 手机号码验证 isUppercaseWord, //是否是大写 isZhWord, //是否是中文 isNumber, //是否是数字 isLicensePlate //验证输入车牌是否正确 uniqBy //数组内对象去重 futureDate, //未来几天 默认七天 formatDay // 格式化年月日 搭配useDay Hook使用 } from '@/utils/utils' ```