vite_ts
vue+vue-router+pinia+vite+typescript+prettier+eslint+stylelint+lint-staged+commitlint+tailwindcss
打包工具由webpack换成vite
node版本请使用node18及以上
推荐使用node版本管理工具nvm
使用package.json内的脚本 'npm run commit' 提交代码
使用package.json内的脚本 'npm run commit' 提交代码
全局状态存储中以 map 为前缀的state状态都是用于数据检索用的 不建议用于页面展示
css框架使用了tailwindcss
解决文件行尾与prettier冲突 新项目根目录下新建.gitattributes文件(详细解决方案:https://juejin.cn/post/6844904062987550733)
老项目添加需要执行以下git命令
git rm --cached -r .
git reset --hard
.gitattributes
*.js eol=lf
*.jsx eol=lf
*.json eol=lf
iconfont字体图标渐变色
<!-- tailwindcss -->
<i class="iconfont icon-zhitimoshi bg-gradient-to-r from-pink-500 to-violet-500 bg-clip-text text-64 text-transparent"></i>
.iconfont {
background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(180deg, #BB8A65 0%, #E3BA9B 100%);
}
导视开发提测流程
- 修改项目中根目录下的
.drone.yml找到name: 上传zip到iot测试接口platformProgramAdd文件配置,如下所示:
commands:
# # 自动授权
# - export projectCode="projectCode=project-inluar4ppcxvciefgb_ila"
- export name="导视包ci流程测试" # 应用名称(自行填写 必填)
- export version=$(cat .tags) # 应用版本 (无需填写)
- export sourceId="8" # 应用来源id(默认为8 即测试环境专用 保持默认即可)
- export genre="localpack" # 应用类型 本地资源包 保持默认即可 [outchain, localpack]
- export resolution="1080*1920竖屏" # 分辨率(自行填写)[1080*1920竖屏, 1920*1080横屏, 3840*2160横屏, 2160*3840竖屏]
- export package="/drone/src/target/$DRONE_REPO_NAME.$(cat .tags).zip" # zip包名称 保持默认即可
- export des=$CI_COMMIT_MESSAGE # 应用描述 保持默认即可
- python3 iot_upload.py
- 修改项目中根目录下的
.tpl文件中的git地址配置,如下所示:
<!-- 在.tpl文件的第6行,修改项目git地址 -->
<font color=[TPL_STATUS_COLOR] size="3">
项目git地址:https://git.1000my.com/
</font>
<!-- 以上海浦项写字楼项目为例,如下所示: -->
<font color=[TPL_STATUS_COLOR] size="3">
项目git地址:https://git.1000my.com/project_shpuxiang/shpuxiang_daoshi_vue
</font>
- 钉钉群机器人配置(钉钉机器人接入官方文档)
- 在项目钉钉群界面点击右上角的群设置按钮。
- 在群设置界面点击智能群助手按钮。
- 在智能群助手界面点击添加机器人按钮。
- 在弹出的弹窗界面中点击添加机器人右边的小齿轮按钮。
- 在选择添加机器人列表中选择自定义机器人。
- 在机器人详情界面点击添加按钮。
- 在添加机器人界面可以修改机器人的头像以及名字,在安全设置选项中选择自定义关键字,并添加地址关键字,勾选我已阅读并同意《自定义机器人服务及免责条款》,然后点击完成按钮。
- 完成创建后会自动生成机器人的Webhook地址,例如:
https://oapi.dingtalk.com/robot/send?access_token=XXXXXX。复制地址中的access_token=后面的值,修改项目中根目录下的.drone.yml文件中的钉钉机器人token配置,如下所示:
# 钉钉通知
- name: dingTalk notification
pull: if-not-exists
image: lddsb/drone-dingtalk-message
failure: ignore
settings:
token: 5f1337cd8cb70e007d2693f70a3ca89fdec543781a9a9fe2f5519e061a1820a8
-
项目提测步骤:
- 通过
npm run commit命令提交本地代码。
git push 提交代码到项目远端dev分支
- 在远端仓库合并
dev分支到test分支
-
Vue3常用工具库函数VueUse
-
开发 及内置组件使用说明见以下文档
-
所有需要写在App.vue内的组件请放到PublicComponent组件
-
地图SDK地址:https://1000my.com/mapapidoc/index.html
-
所有跳到导航页面之前请先调用 @/utils/Class/Brand.ts 来生成一个新的shop数据 以更新store内的shop数据 (本身操作是店铺除外)看以下demo
-
function nav(activity: Activity) {
return new Promise<Shop>((resolve, reject) => {
if (activity.shopCode?.length) {
const shop = mapShopListByCode.value[activity.shopCode]?.[0]
if (shop) {
resolve(shop)
} else {
reject('Unable to match store')
}
return
}
if (activity.point?.length) {
const { title, point, fileUrl, titleEn } = activity
const [buildingOrder, floorOrder, yaxis] = splitStringToArray(point)
const navBuildingInfo = buildingList.value.find(item => item.buildingOrder === buildingOrder)
const shop = new Brand({
shopName: title,
shopNameEn: titleEn,
floorOrder,
floor: navBuildingInfo?.floorList?.find(item => item.floorOrder === floorOrder)?.floor ?? '',
logoUrl: fileUrl[0],
yaxis,
buildingOrder,
building: navBuildingInfo?.building
})
resolve(shop)
}
})
}
组件使用
AutoBackNotification
| props |
type |
desc |
default |
| title |
string |
提示文字 |
'' |
| delay |
number |
倒计时的数字 |
0 |
Marquees
| props |
type |
desc |
default |
| content |
string |
滚动的内容 |
'' |
| delay |
number |
第一次滚动时的延迟 时间 |
0.8 |
| speed |
number |
滚动速度 |
40 |
Icon
| props |
type |
desc |
default |
| type |
IconType |
图标类型 |
'' |
| color |
string |
填充颜色 |
rgba(0, 0, 0, 1) |
Icon组件大小由父容器决定 所以需要给父容器指定宽高 type类型详见icon.d.ts
Tabs
| props |
type |
desc |
default |
| list |
TabItem[] |
数据源 |
[] |
| indicateColor |
string |
选中的颜色 |
#fff |
TabItem类型 详见base.d.ts
| events |
type |
desc |
| click |
(item: TabItem, index: number)=>void |
点击tab |
组件默认ui无法满足设计稿时 可直接修改组件源码以满足设计稿 或者通过slot插槽自定义ui 详见以下demo
<Tabs :list="tabs" class="p-1" indicate-color="#333">
<template #default="{ item, index, tabActiveIndex }">
<div class="relative z-0 p-11 flex-center">
<div class="h-10 w-10">
<Icon :type="item.icon" />
</div>
<div class="text-24 transition-all" :class="index === tabActiveIndex ? 'text-white' : 'text-gray-400'">
<p class="leading-none">{{ item.title }}</p>
<p class="leading-none">{{ item.titleEn }}</p>
</div>
</div>
</template>
</Tabs>
ScrollView
| props |
type |
desc |
default |
| list |
array | string |
监听的数据源 当数据源改动时会自动调用refresh重新计算滚动高度 |
- |
| scrollbar |
boolean |
显示滚动条 |
false |
| scrollX |
boolean |
是否需要横向滚动 |
false |
| refreshDelay |
number |
延迟初始化实例的时间 |
20 |
| scrollTop |
boolean |
当list数据改变时是否自动回到顶部或者左边(scrollX为true时) |
true |
| observeImage |
boolean |
是否监听图片(有瀑布流布局的地方建议开启) |
false |
| stopPropagation |
boolean |
是否阻止事件冒泡。多用在嵌套 scroll 的场景。 |
false |
| pullUp |
boolean |
是否下拉刷新 |
false |
EffectFade
| props |
type |
desc |
default |
| list |
array |
内部渲染需要的数据 |
[] |
| pagination |
boolean | PaginationOptions |
是否开启提示点 |
false |
此组件只初始化swiper轮播等相关逻辑 只做展示 dom节点自行实现 通过作用域插槽可拿到循环的每一项数据 作用域插槽字段: { item }
<script lang="ts" setup>
import {ref} from 'vue'
import EffectFade from '@/components/EffectFade/EffectFade.vue'
const list = [
'https://img1.baidu.com/it/u=847956157,2750448390&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1695402000&t=85436b1a506b8cb8849887ab93c4ea2f',
'https://img0.baidu.com/it/u=937072262,2445742246&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1695402000&t=61d122c4ffd7b8f9e5feee57e4eff73a'
]
</script>
<template>
<div class="w-[400px] h-[150px] mx-auto">
<EffectFade pagination :list="list">
<template v-slot="{ item }">
<div class="w-[400px] h-[150px]">
<img :src="item" class="cover" alt="" />
</div>
</template>
</EffectFade>
</div>
</template>
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 |
车牌号或者车位号 |
[] |
| btnText |
string |
按钮提示文字 |
'' |
| searchMethod |
'车牌'|'车位' |
找车方式 |
'车牌' |
| events |
type |
desc |
| handle-input |
function |
点击输入框 |
| confirm |
function |
确认找车 即点击找车按钮触发 |
车牌输入框组件现在接受一个slot插槽 可以用来点击时显示loading提示或其他内容
PlateKeyboard
| props |
type |
desc |
default |
| searchMethods |
string |
找车方式 ['车牌', '车位'] |
'车牌' |
| events |
type |
desc |
| handle-keyboard |
function |
点击找车键盘 参数为点击时的文字 如果为del则会触发del事件 |
| del |
function |
删除 |
Lottie动画组件
| props |
type |
desc |
default |
| isLocale |
boolean |
是否是json本地文件 |
true |
| path |
Record<any, any> |
动画数据 |
{} |
composition hooks 使用
活动导航
const { nav } = useActivityNav() //nav接受参数类型
async function _nav(activity: Activity) {
await nav(activity)
//your code ...
}
通用导航的hooks
<template>
<ScrollView ref="scroll" :list="pathShopList">
<div>
<!-- 经过店铺ui自行实现 -->
</div>
</ScrollView>
</template>
<script setup lang="ts">
import ScrollView from '@/base/ScrollView/ScrollView.vue'
//滚动组件实例传入hooks 在状态改变时能够使其重新计算 重新滚动到顶部
const scroll = ref<InstanceType<typeof ScrollView> | null>(null)
/*
directionInfo: 方向信息
pathShopList: 经过店铺
startNavi: 导航
backPathArray: 导航函数执行时的回调
*/
const { directionInfo, pathShopList, startNavi, backPathArray } = useStartNavi()
/*
passIdx: 经过店铺列表的经过状态索引
reset: 重置索引
*/
const { passIdx, reset } = usePassActive(pathShopList)
/*
replay:重播
pause:暂停
speedUp:加速
handleReplay:设置重播
togglePause: 设置暂停
handleSpeedUp: 设置加速
resetPause: 暂停初始化
scroll是ScrollView组件实例
*/
const { replay, pause, speedUp, handleReplay, togglePause, handleSpeedUp, resetPause } = useMapNavControl(reset, scroll)
/*
methodsList: 路线列表 视图层绑定
methodIdx: 路线选中索引
handleControl:路线选择
selectedWayMethod:此函数大多数情况无需调用 只需调用handleControl即可
*/
const { methodIdx, methodsList, handleControl, resetMethodIdx } = useChangeNavMethod(backPathArray, resetPause, reset, scroll)
/*
viewIcon: 文字及提示icon信息
setCameraViews: 导航视角
setText:设置文字
*/
const { viewIcon, setCameraViews, setText } = useCameraViews()
</script>
日期及天气
const {whickWeek} = useDay()
const {currentTime} = useTime()
const {weather, icon} = useWeather()
useSearchShop.ts
import {ref} from 'vue'
import {useSearchShop} from '@/composables/useSearchShop'
const keywords = ref('')
const searchMethods = ref(0) //0:键盘搜索 1:手写搜索
//筛选之后的店铺列表
const {searchShopList} =useSearchShop(keywords,searchMethods)
usePage.ts
<ScrollView ref="scroll" pull-up @scroll-end="scrollEnd" :list="pathShopList">
<div>
your html code...
</div>
</ScrollView>
const { scrollEnd, pageList, loaded } =usePage(shopList, scroll)
其余hooks详见脚手架内的composables文件夹
项目内使用的工具函数
import {
randomNumber, //两个数字之间的随机数
isPhoneNumber, // 手机号码验证
isUppercaseWord, //是否是大写
isZhWord, //是否是中文
isNumber, //是否是数字
isLicensePlate //验证输入车牌是否正确
uniqBy //数组内对象去重
futureDate, //未来几天 默认七天
formatDay, // 格式化年月日
isInDuringDate, //当前时间是否在指定时间段内
addPrefixByRecursive, //指定的资源加上地址前缀
splitStringToArray, //字符串点位转换成数组需以下划线 '_' 连接
trimAll //去除字符串所有空格
} from '@/utils/utils'