Browse Source

refactor(project): 修复遗留bug,更新项目文档

master
wangxiang 2 years ago
parent
commit
ee57aefe65
  1. 13
      CHANGELOG.md
  2. 21
      LICENSE
  3. 200
      README.md
  4. 8
      src/api/platform/core/entity/upload.ts
  5. 23
      src/api/platform/system/controller/region.ts
  6. 6
      src/api/platform/system/controller/user.ts
  7. 3
      src/api/platform/system/entity/file.ts
  8. 395
      src/components/AMap/src/AMapDesigner/index.vue
  9. 2
      src/components/Cropper/src/CropperAvatar.vue
  10. 4
      src/components/Dropdown/src/Dropdown.vue
  11. 3
      src/components/Upload/src/BasicUpload.vue
  12. 24
      src/components/Upload/src/UploadModal.vue
  13. 6
      src/components/Upload/src/UploadPreviewModal.vue
  14. 4
      src/views/common/org/org.data.ts
  15. 10
      src/views/system/region/RegionModal.vue
  16. 8
      src/views/system/region/index.vue
  17. 4
      src/views/system/user/UserModal.vue
  18. 2
      src/views/system/user/account/setting/UserInfo.vue

13
CHANGELOG.md

@ -1,12 +1,3 @@ @@ -1,12 +1,3 @@
# 1.0.0 (2022-04-13)
前端架构搭建完毕,目前使用vue这块最新,最前沿的技术栈
基于vbenAdmin2.8.0重构
非常感谢所有通过代码(下面列出的作者)或GitHub上的评论和分类对这个版本做出贡献的人:
[Vben Admin](https://vvbin.cn/doc-next/)
[长沙康来生物有限公司-王翔](https://github.com/wangxiang4/wangxiang4)
# 1.0.0 (2023-01-16)
海豚生态计划-打造一个web端,安卓端,ios端的一个海豚开发平台生态圈,不接收任何商业化,并且完全免费开源(包含高级功能)。

21
LICENSE

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023-PRESENT Dolphin Ecology
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

200
README.md

@ -1,66 +1,166 @@ @@ -1,66 +1,166 @@
# 🐇`kicc-ui`(康来智慧冷链-UI) 基于Vue3的中后台系统 © 长沙康来生物有限公司版权所有
## 🔥 当前版本
`1.0.0` 基础功能已完善,后续功能正在加紧迭代开发中。
## 💡 简介
kicc-ui 是基于vben Admin的模板开发,使用了最新的`vue3`,`vite2`,`TypeScript`等主流技术,支持标本箱配送,监控,地图路线规划,
努力做成中国最好的智慧冷链平台。
## 💥 技术特性
<h1 align="center">
<b>
<a href="https://godolphinx.org"><img src="https://godolphinx.org/images/dolphin-platform-logo.svg" /></a><br>
</b>
</h1>
<p align="center"> 一个快速开发软件的平台 </p>
<p align="center">
<a href="https://godolphinx.org/"><b>Website</b></a>
<a href="https://godolphinx.org/vue3/description.html"><b>Documentation</b></a>
</p>
<div align="center">
<a href="https://godolphinx.org">
<img src="https://img.shields.io/npm/l/vue.svg?sanitize=true">
</a>
<a href="https://gitpod.io/#https://github.com/wangxiang4/dolphin-admin">
<img src="https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod&style=flat-square">
</a>
<a href="https://discord.gg/DREuQWrRYQ">
<img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true"/>
</a>
</div>
## 🐬 介绍
海豚生态计划-打造一个web端,安卓端,ios端的一个海豚开发平台生态圈,不接收任何商业化,并且完全免费开源(包含高级功能)。
## 💪 愿景
让人人都可以快速高效的开发软件
## ✨ 特性
- **最新技术栈**:使用 Vue3/vite2 等前端前沿技术开发
- **TypeScript**: 应用程序级 JavaScript 的语言
- **TypeScript**: 集成TypeScript管控项目,具有可预测的静态类型,提高了代码的可读性、可维护性和可靠性
- **主题**:可配置的主题
- **国际化**:内置完善的国际化方案
- **Mock 数据** 内置 Mock 数据方案
- **权限** 内置完善的动态路由权限生成方案
- **组件** 二次封装了多个常用的组件
## 🧬 开发准备前,你必须所需要具备的技术
- **权限**:内置完善的动态嵌套路由权限生成实现
- **组件**:二次封装了多个常用的组件
- **地图**:高德地图在线规划路线导航
- **多租户**:使用SASS提供独立的、隔离的数据管理,在线无缝切换多个租户数据
- **动画**:内部默认实现大量的动画过渡、让组件切换更加丝滑
- **UI组件库**:集成ant-design-vue,提供了一系列高质量、易于使用的组件,可快速迭代项目开发
- **图表组件**:集成echarts让图表组件开箱即用,提供了各种类型的图表和强大的可定制性
- **工具**:集成lodash,@vueuse/core,降低相关API的学习成本,提高工作效率,封装了诸多常用的函数和操作,让写vue3也可以甜甜的
- **状态管理**:集成pinia采用了基于函数式编程的方式来处理状态的更新和变化,更加直观的 API 和高性能的响应式状态管理方案
- **可拖拽**:集成SortableJS提供了用于创建可排序列表和网格的功能,可以用于实现拖放排序等交互式用户界面
- **富文本编辑器**:一个基于 JavaScript 的所见即所得的富文本编辑器,TinyMCE的功能非常灵活和高度可定制,开源版功能也比较齐全
- **高级表格组件**:集成vxe-table提供了丰富的表格功能和灵活的配置选项,可以用于展示和编辑各种类型的数据,同时也支持异步数据和虚拟滚动等优化性能的特性
- **渐进式网络应用程序**:集成vite-plugin-pwa,用于将Vue.js或其他前端应用程序转换为具有离线缓存和本地存储能力的PWA
## <img width="28" style="vertical-align:middle" src="https://godolphinx.org/images/hacktoberfest-logo.svg"> 黑客节
加入[Github HackToberFest](https://hacktoberfest.com/) 开始为此项目做出贡献.
## 🔨 开发目录
- [node](http://nodejs.org/) 和 [git](https://git-scm.com/) -项目开发环境
- [Vite](https://vitejs.dev/) - 熟悉 vite 特性
- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法
- [TypeScript](https://www.typescriptlang.org/) - 熟悉`TypeScript`基本语法
- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法
- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router 基本使用
- [Ant-Design-Vue](https://2x.antdv.com/docs/vue/introduce-cn/) - ui 基本使用
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法
```
├─ dolphin-admin -- 海豚vue3-管理系统
│ ├─build -- 构建打包配置
│ │ ├─config -- 通用配置
│ │ ├─generate -- 资源生成配置(less变量,icon)
│ │ ├─script -- 附加构建脚本
│ │ ├─vite -- vite配置
│ ├─docker -- docker容器配置
│ ├─public -- 公共资源目录
│ ├─src -- 开发的目录
│ │ ├─api -- 请求接口
│ │ │ ├─common -- 通用请求数据类型(根据后端通用实体类定义)
│ │ │ │ ├─base -- 基础类型
│ │ │ │ ├─data -- 数据类型
│ │ │ ├─platform -- 微服务框架平台业务api
│ │ │ │ ├─common -- 通用业务模块api
│ │ │ │ ├─core -- 系统核心业务api
│ │ │ │ ├─monitor -- 运维监控业务模块api
│ │ │ │ ├─system -- 系统业务模块api
│ │ ├─assets -- 开发资源目录(会被打包编译)
│ │ ├─components -- 全局组件
│ │ │ ├─AMap -- 高德地图设计器
│ │ │ ├─Application -- 应用核心组件
│ │ │ ├─Authority -- 角色权限控制
│ │ │ ├─Basic -- 系统基础组件
│ │ │ ├─Button -- 按钮
│ │ │ ├─ClickOutSide -- 元素点击监听包装
│ │ │ ├─Container -- 组件包装容器
│ │ │ ├─ContextMenu -- 右击菜单上下文
│ │ │ ├─CountDown -- 验证码倒计时
│ │ │ ├─CountTo -- 计数器
│ │ │ ├─Cropper -- 图片裁剪
│ │ │ ├─Description -- 详细页面
│ │ │ ├─Drawer -- 弹出抽屉
│ │ │ ├─Dropdown -- 下拉列表
│ │ │ ├─Excel -- Excel导入导出
│ │ │ ├─Form -- 动态表单
│ │ │ ├─Icon -- icon图标
│ │ │ ├─Loading -- 加载遮罩层
│ │ │ ├─Markdown -- Markdown编辑器
│ │ │ ├─Menu -- 顶部菜单模式菜单
│ │ │ ├─Modal -- 弹出模态框
│ │ │ ├─Page -- 页面包装
│ │ │ ├─Qrcode -- 二维码生成
│ │ │ ├─Scrollbar -- 滚动条
│ │ │ ├─SimpleMenu -- 侧边栏菜单
│ │ │ ├─StrengthMeter -- 密码强度检查
│ │ │ ├─Table -- 动态表格
│ │ │ ├─Time -- 当前时间显示
│ │ │ ├─Tinymce -- 功能齐全的富文本编辑器
│ │ │ ├─Transition -- 过度动画
│ │ │ ├─Tree -- 树形控件
│ │ │ ├─Upload -- 文件上传
│ │ ├─directives -- 自定义指令
│ │ ├─enums -- 全局枚举
│ │ ├─hooks -- vue组合API钩子工具
│ │ │ ├─component -- 组件相关钩子
│ │ │ ├─core -- 系统核心相关钩子
│ │ │ ├─event -- 事件相关钩子
│ │ │ ├─setting -- 全局设置相关钩子
│ │ │ ├─web -- 网页相关钩子
│ │ ├─layouts -- 系统总布局
│ │ │ ├─default -- 默认总系统布局框架组件
│ │ │ ├─iframe -- 内嵌页面
│ │ │ ├─page -- 路由模块页面
│ │ ├─locales -- 国际化
│ │ ├─logics -- 系统全局控制逻辑
│ │ ├─router -- 路由
│ │ ├─settings -- 默认全局设置配置
│ │ ├─store -- 全局状态管理
│ │ ├─utils -- 工具类
│ │ │ ├─auth -- 存储授权信息缓存
│ │ │ ├─cache -- 缓存实例工具
│ │ │ ├─event -- 事件工具
│ │ │ ├─factory -- 组件工厂
│ │ │ ├─file -- 文件工具
│ │ │ ├─helper -- 路由转换帮助工具
│ │ │ ├─http -- api请求工具
│ │ │ ├─lib -- 图表组件库
│ │ ├─views -- 页面模块组件
│ │ │ ├─common -- 通用业务页面
│ │ │ ├─core -- 系统核心业务页面
│ │ │ ├─dashboard -- 仪表板分析页面
│ │ │ ├─level -- 多级菜单页面
│ │ │ ├─monitor -- 运维监控业务页面
│ │ │ ├─system -- 系统业务页面
│ ├─types -- 全局类型定义
```
## 🍀 需要注意的地方
##1.钩子工具跟项目基础工具区别
- **hooks目录: 基于Vue3-Composition-API二次封装的使用实用程序的组合api,目的为了扩展@vueuse/core组合api**
- **utils目录: 二次封装,或原生写的工具类,不会去使用一些框架的钩子**
```bash
两者的区别:
可以理解为两者都是工具,但是区别在于utils目录没有使用Vue3-Composition-API封装,
hooks目录使用了Vue3-Composition-API,hooks目录说的在明白一点就是在扩展自己的Vue3-Composition-API
```
**Vue3-Composition-API官方介绍: https://staging-cn.vuejs.org/guide/extras/composition-api-faq.html**
#2.打包前应该如何执行typescript类型检查
### 1.打包前应该如何执行typescript类型检查
- **vite是不支持typescript类型检查,因为没必要,现在的开发工具都是支持eslint的,让开发工具接管类型检查就行啦**
- **vite官网TypeScript介绍:https://vitejs.bootcss.com/guide/features.html#typescript**
- **注意:既然vite不支持typescript类型检查,那我们就应该要在发布编译阶段手动执行 vue-tsc 命令检查类型,要不然完全体现不出typescript在项目中的作用,使用了typescript就应该要检查代码是否符合类型规范**
- **注意:既然vite不支持typescript类型检查,那我们就应该要在发布编译阶段手动执行 vue-tsc 命令检查类型是否符合typescript类型规范**
## 🗽 启动项目
```bash
## 🤔 一起讨论
加入我们的 [Discord](https://discord.gg/DREuQWrRYQ) 开始与大家交流。
# 进入项目目录
cd kicc-ui
## 🤗 我想成为开发团队的一员!
欢迎😀!我们正在寻找有才华的开发者加入我们,让海豚开发平台变得更好!如果您想加入开发团队,请联系我们,非常欢迎您加入我们!💖
# 安装依赖
yarn install
## 在线一键设置
您可以使用 Gitpod,一个在线 IDE(开源免费)来在线贡献或运行示例。
# 运行
yarn serve
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/wangxiang4/dolphin-admin)
# 打包
yarn build
## 📄 执照
[Dolphin Development Platform 是获得MIT许可](https://github.com/wangxiang4/dolphin-admin/blob/master/LICENSE) 的开源软件 。
```

8
src/api/platform/core/entity/upload.ts

@ -6,9 +6,7 @@ @@ -6,9 +6,7 @@
* @create: 2022/4/8
*/
import type { File as OssFile } from '/@/api/platform/system/entity/file';
/** oss上传返回结果对象 */
export interface UploadResult {
bucketName: string;
fileName: string;
url: string;
}
export type UploadResult = OssFile

23
src/api/platform/system/controller/region.ts

@ -16,22 +16,13 @@ enum Api { @@ -16,22 +16,13 @@ enum Api {
del = '/system_proxy/system/region/remove'
}
export const listRegion = (params?: Partial<RegionParams>) => {
let url = Api.lazyList;
if (params?.name || params?.code || params?.beginTime || params?.endTime) url = Api.list;
return defHttp.get({ url: url, params });
};
export const listRegionCascade = (params?: Partial<RegionParams>) => defHttp.get({ url: Api.lazyList, params }).then(res => {
return res.map(item => {
const { children, ...result } = item;
return { ...result, isLeaf: !!!children };
});
});
export const addRegion = (params:Partial<Region>) => defHttp.post({ url: Api.add,data:params });
export const editRegion = (params:Partial<Region>) => defHttp.put({ url: Api.edit,data:params });
export const listRegion = (params?: Partial<RegionParams>) => defHttp.get({ url: Api.list, params });
export const lazyListRegion = (params?: Partial<RegionParams>) => defHttp.get({ url: Api.lazyList, params });
export const addRegion = (params:Partial<Region>) => defHttp.post({ url: Api.add, data: params });
export const editRegion = (params:Partial<Region>) => defHttp.put({ url: Api.edit, data: params });
export const getRegion = (id: string) => defHttp.get<ResultVo<Region>>({ url: `${Api.get}/${id}` });

6
src/api/platform/system/controller/user.ts

@ -14,7 +14,6 @@ enum Api { @@ -14,7 +14,6 @@ enum Api {
add = '/system_proxy/system/user/save',
get = '/system_proxy/system/user',
edit = '/system_proxy/system/user/update',
editUser = '/system_proxy/system/user/updateUser',
del = '/system_proxy/system/user/remove',
updatePwd = '/system_proxy/system/user/updatePwd',
resetPwd='/system_proxy/system/user/resetPwd',
@ -31,11 +30,8 @@ export const listUser = (params?: Partial<UserParams>) => defHttp.get<UserResult @@ -31,11 +30,8 @@ export const listUser = (params?: Partial<UserParams>) => defHttp.get<UserResult
/** 新增用户 */
export const addUser = (params: Partial<User>) => defHttp.post({ url: Api.add, data: params });
/** 修改用户关联用户角色表 */
export const editUserRole = (params: Partial<User>) => defHttp.put({ url: Api.edit, data: params });
/** 修改用户 */
export const editUser = (params: Partial<User>) => defHttp.put({ url: Api.editUser, data: params });
export const editUser = (params: Partial<User>) => defHttp.put({ url: Api.edit, data: params });
/** 查询用户详细 */
export const getUser = (id: string) => defHttp.get<ResultVo>({ url: `${Api.get}/${id}` });

3
src/api/platform/system/entity/file.ts

@ -19,6 +19,9 @@ export interface File extends CommonEntity { @@ -19,6 +19,9 @@ export interface File extends CommonEntity {
original: string;
type: string;
fileSize: number;
availablePath: string;
duration: number;
mimeType: string;
[key: string]: any;
}

395
src/components/AMap/src/AMapDesigner/index.vue

@ -112,11 +112,11 @@ @@ -112,11 +112,11 @@
import { useDebounceFn } from '@vueuse/core';
import { EventSourcePolyfill } from 'event-source-polyfill/src/eventsource';
import { getAccessToken } from '/@/utils/auth';
import { useTimeoutFn } from '@vueuse/core'
/** 类型规范统一声明定义区域 */
interface MapState {
first: boolean;
loading: boolean;
defaultZoom: number;
toggleOperatePanelClass: Recordable;
toggleStatus: boolean;
@ -168,8 +168,6 @@ @@ -168,8 +168,6 @@
const mapState = reactive<MapState>({
/** 首次初始化 */
first: false,
/** 遮罩层状态 */
loading: false,
/** 默认缩放大小 */
defaultZoom: 7,
/** 面板类样式属性 */
@ -242,53 +240,75 @@ @@ -242,53 +240,75 @@
onBeforeMount(() => {
if (!instance) return;
mapState.loading = true;
//
AMapLoader.load({
key: mapState.mapConfig.amapKey,
version: '2.0',
plugins: ['AMap.MarkerCluster', 'AMap.Driving']
}).then(async AMap => {
//
map = new AMap.Map(instance.refs.mapview, mapState.mapConfig.options);
map.plugin(['AMap.ToolBar', 'AMap.MapType', 'AMap.ControlBar', 'AMap.Scale'], () => {
if (mapProps.mapControl?.includes('toolBar')) {
//
map.addControl(new AMap.ToolBar());
}
if (mapProps.mapControl?.includes('controlBar')) {
// ,,,
map.addControl(new AMap.ControlBar());
}
if (mapProps.mapControl?.includes('scale')) {
//
const scale = new AMap.Scale();
scale.show();
map.addControl(scale);
}
if (mapProps.mapControl?.includes('mapType')) {
//
map.addControl(
new AMap.MapType({
defaultType: 0,
showRoad: true
})
);
}
});
map.on('zoomchange', ctx => {
mapState.defaultZoom = subtract(divide(map.getZoom(),2), 1);
});
useTimeoutFn(() => {
//
map = new AMap.Map(instance.refs.mapview, mapState.mapConfig.options);
map.plugin(['AMap.ToolBar', 'AMap.MapType', 'AMap.ControlBar', 'AMap.Scale'], () => {
if (mapProps.mapControl?.includes('toolBar')) {
//
map.addControl(new AMap.ToolBar());
}
if (mapProps.mapControl?.includes('controlBar')) {
// ,,,
map.addControl(new AMap.ControlBar());
}
if (mapProps.mapControl?.includes('scale')) {
//
const scale = new AMap.Scale();
scale.show();
map.addControl(scale);
}
if (mapProps.mapControl?.includes('mapType')) {
//
map.addControl(
new AMap.MapType({
defaultType: 0,
showRoad: true
})
);
}
});
map.on('zoomchange', ctx => {
mapState.defaultZoom = subtract(divide(map.getZoom(),2), 1);
});
//
hospitalMarkerCluster = new AMap.MarkerCluster(map, [], {
gridSize: 80,
maxZoom: 14,
renderMarker(ctx) {
const { marker, data } = ctx;
if (Array.isArray(data) && data[0]) {
const { label, mapOrientation, mapNotify } = data[0];
let content = `<img width="30px" height="30px" style="transform: scale(1) rotate(${360 - Number(mapOrientation)}deg);" src='${hospital}'/>`;
//
hospitalMarkerCluster = new AMap.MarkerCluster(map, [], {
gridSize: 80,
maxZoom: 14,
renderMarker(ctx) {
const { marker, data } = ctx;
if (Array.isArray(data) && data[0]) {
const { label, mapOrientation, mapNotify } = data[0];
let content = `<img width="30px" height="30px" style="transform: scale(1) rotate(${360 - Number(mapOrientation)}deg);" src='${hospital}'/>`;
marker.setLabel({
direction: 'bottom',
//
offset: new AMap.Pixel(-4, 0),
//
content: `<div>${label}</div>`
});
marker.setOffset(new AMap.Pixel(-18, -10));
if (mapNotify) {
content = `<img width="30px" height="30px" style="transform: scale(1) rotate(${360 - Number(mapOrientation)}deg);" src='${hospitalTwinkle}'/>`;
}
marker.setContent(content);
}
},
renderClusterMarker(ctx) {
const { clusterData, marker, count } = ctx;
let content = `<img width="30px" height="30px" src='${hospital}'/>`;
if(clusterData.some(item => item.mapNotify)){
content = `<img width="30px" height="30px" src='${hospitalTwinkle}'/>`;
}
marker.setContent(content);
const label = count == 1 ? clusterData[0].label : `医院数量:${count}`;
marker.setLabel({
direction: 'bottom',
//
@ -297,45 +317,38 @@ @@ -297,45 +317,38 @@
content: `<div>${label}</div>`
});
marker.setOffset(new AMap.Pixel(-18, -10));
if (mapNotify) {
content = `<img width="30px" height="30px" style="transform: scale(1) rotate(${360 - Number(mapOrientation)}deg);" src='${hospitalTwinkle}'/>`;
}
marker.setContent(content);
}
},
renderClusterMarker(ctx) {
const { clusterData, marker, count } = ctx;
let content = `<img width="30px" height="30px" src='${hospital}'/>`;
if(clusterData.some(item => item.mapNotify)){
content = `<img width="30px" height="30px" src='${hospitalTwinkle}'/>`;
}
marker.setContent(content);
const label = count == 1 ? clusterData[0].label : `医院数量:${count}`;
marker.setLabel({
direction: 'bottom',
//
offset: new AMap.Pixel(-4, 0),
//
content: `<div>${label}</div>`
});
marker.setOffset(new AMap.Pixel(-18, -10));
}
});
hospitalMarkerCluster.on('click', ctx => {
const { lnglat } = ctx;
map.setZoomAndCenter(18, lnglat);
});
});
hospitalMarkerCluster.on('click', ctx => {
const { lnglat } = ctx;
map.setZoomAndCenter(18, lnglat);
});
//
orgMarkerCluster = new AMap.MarkerCluster(map, [], {
gridSize: 80,
maxZoom: 14,
renderMarker(ctx) {
const { marker, data } = ctx;
if (Array.isArray(data) && data[0]) {
const { label, mapOrientation } = data[0];
const content = `<img width="30px" height="30px" style="transform: scale(1) rotate(${360 - Number(mapOrientation)}deg);" src='${redFlag}'/>`;
//
orgMarkerCluster = new AMap.MarkerCluster(map, [], {
gridSize: 80,
maxZoom: 14,
renderMarker(ctx) {
const { marker, data } = ctx;
if (Array.isArray(data) && data[0]) {
const { label, mapOrientation } = data[0];
const content = `<img width="30px" height="30px" style="transform: scale(1) rotate(${360 - Number(mapOrientation)}deg);" src='${redFlag}'/>`;
marker.setContent(content);
marker.setLabel({
direction: 'bottom',
//
offset: new AMap.Pixel(-4, 0),
//
content: `<div>${label}</div>`
});
marker.setOffset(new AMap.Pixel(-18, -10));
}
},
renderClusterMarker(ctx) {
const { clusterData, marker, count } = ctx;
const content = `<img width="30px" height="30px" src='${redFlag}'/>`;
marker.setContent(content);
const label = count == 1 ? clusterData[0].label : `医检机构数量:${count}`;
marker.setLabel({
direction: 'bottom',
//
@ -345,37 +358,37 @@ @@ -345,37 +358,37 @@
});
marker.setOffset(new AMap.Pixel(-18, -10));
}
},
renderClusterMarker(ctx) {
const { clusterData, marker, count } = ctx;
const content = `<img width="30px" height="30px" src='${redFlag}'/>`;
marker.setContent(content);
const label = count == 1 ? clusterData[0].label : `医检机构数量:${count}`;
marker.setLabel({
direction: 'bottom',
//
offset: new AMap.Pixel(-4, 0),
//
content: `<div>${label}</div>`
});
marker.setOffset(new AMap.Pixel(-18, -10));
}
});
orgMarkerCluster.on('click', ctx => {
const { lnglat } = ctx;
map.setZoomAndCenter(18, lnglat);
});
});
orgMarkerCluster.on('click', ctx => {
const { lnglat } = ctx;
map.setZoomAndCenter(18, lnglat);
});
//
courierUserMarkerCluster = new AMap.MarkerCluster(map, [], {
gridSize: 80,
maxZoom: 14,
renderMarker(ctx) {
const { marker, data } = ctx;
if (Array.isArray(data) && data[0]) {
const { label, mapOrientation } = data[0];
const content = `<img width="30px" height="30px" style="transform: scale(1) rotate(${360 - Number(mapOrientation)}deg);" src='${medicalKit}'/>`;
//
courierUserMarkerCluster = new AMap.MarkerCluster(map, [], {
gridSize: 80,
maxZoom: 14,
renderMarker(ctx) {
const { marker, data } = ctx;
if (Array.isArray(data) && data[0]) {
const { label, mapOrientation } = data[0];
const content = `<img width="30px" height="30px" style="transform: scale(1) rotate(${360 - Number(mapOrientation)}deg);" src='${medicalKit}'/>`;
marker.setContent(content);
marker.setLabel({
direction: 'bottom',
//
offset: new AMap.Pixel(-4, 0),
//
content: `<div>${label}</div>`
});
marker.setOffset(new AMap.Pixel(-18, -10));
}
},
renderClusterMarker(ctx) {
const { clusterData, marker, count } = ctx;
const content = `<img width="30px" height="30px" src='${medicalKit}'/>`;
marker.setContent(content);
const label = count == 1 ? clusterData[0].label : `收样员数量:${count}`;
marker.setLabel({
direction: 'bottom',
//
@ -385,102 +398,87 @@ @@ -385,102 +398,87 @@
});
marker.setOffset(new AMap.Pixel(-18, -10));
}
},
renderClusterMarker(ctx) {
const { clusterData, marker, count } = ctx;
const content = `<img width="30px" height="30px" src='${medicalKit}'/>`;
marker.setContent(content);
const label = count == 1 ? clusterData[0].label : `收样员数量:${count}`;
marker.setLabel({
direction: 'bottom',
//
offset: new AMap.Pixel(-4, 0),
//
content: `<div>${label}</div>`
});
marker.setOffset(new AMap.Pixel(-18, -10));
}
});
courierUserMarkerCluster.on('click', ctx => {
const { lnglat } = ctx;
map.setZoomAndCenter(18, lnglat);
});
});
courierUserMarkerCluster.on('click', ctx => {
const { lnglat } = ctx;
map.setZoomAndCenter(18, lnglat);
});
//
scanCourierUserCircleRange = new AMap.Circle({
radius: 14000,
borderWeight: 3,
strokeColor: '#3600ff',
strokeOpacity: 0,
strokeWeight: 6,
fillOpacity: 0,
strokeStyle: 'dashed',
strokeDasharray: [8, 8],
fillColor: '#1791fc',
zIndex: 50
});
//
scanCourierUserCircleRange = new AMap.Circle({
radius: 14000,
borderWeight: 3,
strokeColor: '#3600ff',
strokeOpacity: 0,
strokeWeight: 6,
fillOpacity: 0,
strokeStyle: 'dashed',
strokeDasharray: [8, 8],
fillColor: '#1791fc',
zIndex: 50
});
// 线
driving = new AMap.Driving({
map: map,
panel: instance.refs.mapPanel
});
// 线
driving = new AMap.Driving({
map: map,
panel: instance.refs.mapPanel
});
//
const hospitalList = await listHospital({ size: 40, mapNotify: '1' });
mapState.hospitalList = hospitalList.data?.map(item => ({
value: item.id,
label: item.name,
mapLat: item.mapLat,
mapLng: item.mapLng,
mapNotify: !!~~item.mapNotify,
mapOrientation: item.mapOrientation
}));
const hospitalPoints = mapState.hospitalList.map(hospital => ({
lnglat: [hospital.mapLng, hospital.mapLat], ...hospital
}));
hospitalMarkerCluster?.setData(hospitalPoints);
const orgList = await listOrg({ size: 40 });
mapState.orgList = orgList.data?.map(item => ({
value: item.id,
label: item.name,
mapOrientation: item.mapOrientation,
mapLat: item.mapLat,
mapLng: item.mapLng
}));
const orgPoints = mapState.orgList.map(org => ({
lnglat: [org.mapLng, org.mapLat], ...org
}));
orgMarkerCluster?.setData(orgPoints);
//
const hospitalList = await listHospital({ size: 40, mapNotify: '1' });
mapState.hospitalList = hospitalList.data?.map(item => ({
value: item.id,
label: item.name,
mapLat: item.mapLat,
mapLng: item.mapLng,
mapNotify: !!~~item.mapNotify,
mapOrientation: item.mapOrientation
}));
const hospitalPoints = mapState.hospitalList.map(hospital => ({
lnglat: [hospital.mapLng, hospital.mapLat], ...hospital
}));
hospitalMarkerCluster?.setData(hospitalPoints);
const orgList = await listOrg({ size: 40 });
mapState.orgList = orgList.data?.map(item => ({
value: item.id,
label: item.name,
mapOrientation: item.mapOrientation,
mapLat: item.mapLat,
mapLng: item.mapLng
}));
const orgPoints = mapState.orgList.map(org => ({
lnglat: [org.mapLng, org.mapLat], ...org
}));
orgMarkerCluster?.setData(orgPoints);
// ssegps
eventSource = new EventSourcePolyfill(mapDesigner.sseUrl, {
headers: { Authorization: `Bearer ${getAccessToken()}` }
});
// ssegps
eventSource = new EventSourcePolyfill(mapDesigner.sseUrl, {
headers: { Authorization: `Bearer ${getAccessToken()}` }
});
eventSource.onopen = function (ev) {
console.info(ev,'建立连接。。。');
};
eventSource.onmessage = function (ev) {
try {
let { data } = ev;
let mapLogistic = JSON.parse(data);
let courierUser = mapState.courierUserList.find(item => item.value == mapLogistic?.courierUserId);
courierUser && (courierUser.mapLat = mapLogistic.courierLat);
courierUser && (courierUser.mapLng = mapLogistic.courierLng);
} catch (e) {}
console.info(ev);
};
eventSource.onerror = function (ev) {
console.info(ev);
};
//
complete();
eventSource.onopen = function (ev) {
console.info(ev,'建立连接。。。');
};
eventSource.onmessage = function (ev) {
try {
let { data } = ev;
let mapLogistic = JSON.parse(data);
let courierUser = mapState.courierUserList.find(item => item.value == mapLogistic?.courierUserId);
courierUser && (courierUser.mapLat = mapLogistic.courierLat);
courierUser && (courierUser.mapLng = mapLogistic.courierLng);
} catch (e) {}
console.info(ev);
};
eventSource.onerror = function (ev) {
console.info(ev);
};
//
complete();
},350, { immediate: true });
}).catch(error => {
mapState.loading = false;
throw error;
});
});
@ -497,7 +495,6 @@ @@ -497,7 +495,6 @@
if (map) {
setMapDataJson(mapProps.options);
handleSetCourierUserList();
mapState.loading = false;
mapState.first = true;
}
}

2
src/components/Cropper/src/CropperAvatar.vue

@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
showBtn: { type: Boolean, default: true },
btnProps: { type: Object as PropType<ButtonProps> },
btnText: { type: String, default: '' },
uploadApi: { type: Function as PropType<({ file: Blob, name: string }) => Promise<void>> },
uploadApi: { type: Function as PropType<(file: Blob, name: string) => Promise<void>> },
};
export default defineComponent({

4
src/components/Dropdown/src/Dropdown.vue

@ -41,10 +41,10 @@ @@ -41,10 +41,10 @@
import { defineComponent } from 'vue';
import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
import { Icon } from '/@/components/Icon';
import { omit } from 'lodash-es';
import { isFunction } from '/@/utils/is';
import { useDesign } from '/@/hooks/web/useDesign';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export default defineComponent({
name: 'BasicDropdown',
@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
Menu,
MenuItem: Menu.Item,
MenuDivider: Menu.Divider,
Icon,
Icon: createAsyncComponent(() => import('/@/components/Icon')),
Popconfirm,
},
props: {

3
src/components/Upload/src/BasicUpload.vue

@ -54,7 +54,7 @@ @@ -54,7 +54,7 @@
setup(props, { emit, attrs }) {
const { t } = useI18n();
// modal
const [registerUploadModal, { openModal: openUploadModal, closeModal: closeUploadModal }] = useModal();
const [registerUploadModal, { openModal: openUploadModal}] = useModal();
// modal
const [registerPreviewModal, { openModal: openPreviewModal }] = useModal();
@ -103,7 +103,6 @@ @@ -103,7 +103,6 @@
}
return {
closeUploadModal,
registerUploadModal,
openUploadModal,
handleChange,

24
src/components/Upload/src/UploadModal.vue

@ -26,10 +26,11 @@ @@ -26,10 +26,11 @@
</template>
<div class="upload-modal-toolbar">
<Alert :message="getHelpText"
type="info"
banner
class="upload-modal-toolbar__text"
<Alert
:message="getHelpText"
type="info"
banner
class="upload-modal-toolbar__text"
/>
<Upload
@ -48,7 +49,7 @@ @@ -48,7 +49,7 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, reactive, ref, toRefs, unref, computed, PropType } from 'vue';
import { defineComponent, ref, toRefs, unref, computed, PropType } from 'vue';
import { Upload, Alert } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useUploadType } from './useUpload';
@ -62,18 +63,17 @@ @@ -62,18 +63,17 @@
import { warn } from '/@/utils/log';
import FileList from './FileList.vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
import { BasicColumn } from '/@/components/Table';
export default defineComponent({
components: { BasicModal, Upload, Alert, FileList },
props: {
...basicProps,
previewFileList: {
type: Array as PropType<string[]>,
type: Array as PropType<FileItem[]>,
default: () => [],
},
},
emits: ['change', 'register', 'delete', 'success'],
emits: ['change', 'register', 'delete'],
setup(props, { emit }) {
const { t } = useI18n();
const isUploadingRef = ref(false);
@ -214,7 +214,7 @@ @@ -214,7 +214,7 @@
for (const item of fileListRef.value) {
const { status, responseData } = item;
if (status === UploadResultStatus.SUCCESS && responseData) {
fileList.push(responseData.url);
fileList.push(responseData.availablePath);
}
}
//
@ -238,8 +238,8 @@ @@ -238,8 +238,8 @@
}
return {
columns: createTableColumns() as any[],
actionColumn: createActionColumn(handleRemove) as any,
columns: createTableColumns() as BasicColumn[],
actionColumn: createActionColumn(handleRemove) as BasicColumn,
register,
closeModal,
getHelpText,

6
src/components/Upload/src/UploadPreviewModal.vue

@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
import FileList from './FileList.vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { previewProps } from './props';
import { PreviewFileItem } from './typing';
import { FileBasicColumn, PreviewFileItem } from './typing';
import { downloadByUrl } from '/@/utils/file/download';
import { createPreviewColumns, createPreviewActionColumn } from './data';
import { useI18n } from '/@/hooks/web/useI18n';
@ -73,8 +73,8 @@ @@ -73,8 +73,8 @@
register,
closeModal,
fileListRef,
columns: createPreviewColumns() as any[],
actionColumn: createPreviewActionColumn({ handleRemove, handleDownload }) as any,
columns: createPreviewColumns() as FileBasicColumn[],
actionColumn: createPreviewActionColumn({ handleRemove, handleDownload }) as FileBasicColumn,
};
},
});

4
src/views/common/org/org.data.ts

@ -2,7 +2,7 @@ import { BasicColumn } from '/@/components/Table'; @@ -2,7 +2,7 @@ import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { h } from 'vue';
import { Tag } from 'ant-design-vue';
import { listRegionCascade } from '/@/api/platform/system/controller/region';
import { lazyListRegion } from '/@/api/platform/system/controller/region';
export const columns: BasicColumn[] = [
{
@ -206,7 +206,7 @@ export const formSchema: FormSchema[] = [ @@ -206,7 +206,7 @@ export const formSchema: FormSchema[] = [
label: '城市地址',
component: 'ApiCascader',
componentProps: {
api: listRegionCascade,
api: lazyListRegion,
asyncFetchParamKey: 'parentId',
labelField: 'name',
valueField: 'id',

10
src/views/system/region/RegionModal.vue

@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
import { BasicForm, useForm } from '/@/components/Form';
import { regionFormSchema } from './region.data';
import { BasicModal, ModalProps, useModalInner } from '/@/components/Modal';
import { listRegion, addRegion, editRegion, getRegion } from '/@/api/platform/system/controller/region';
import { lazyListRegion, addRegion, editRegion, getRegion } from '/@/api/platform/system/controller/region';
/** 通用变量统一声明区域 */
const state = reactive({
@ -52,11 +52,11 @@ @@ -52,11 +52,11 @@
},
loadData: (treeNode: any) => {
const { id } = treeNode.dataRef;
return listRegion({ parentId: id }).then(res => {
return lazyListRegion({ parentId: id }).then(res => {
treeNode.dataRef.children = (res || [])?.map(item => {
if(item.hasOwnProperty('children')) {
item.isLeaf = false;
} else item.isLeaf = true;
item.hasOwnProperty('children')
? (item.isLeaf = false)
: (item.isLeaf = true);
return item;
});
});

8
src/views/system/region/index.vue

@ -46,15 +46,15 @@ @@ -46,15 +46,15 @@
import { useModal } from '/@/components/Modal';
import RegionModal from './RegionModal.vue';
import { columns, searchFormSchema } from './region.data';
import { delRegion, listRegion } from '/@/api/platform/system/controller/region';
import { delRegion, lazyListRegion } from '/@/api/platform/system/controller/region';
import { useMessage } from '/@/hooks/web/useMessage';
/** 通用变量统一声明区域 */
const { createMessage } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerTable, { reload, getDataSource, setLoading, collapseAll }] = useTable({
const [registerTable, { reload, setLoading, collapseAll }] = useTable({
title: '区域列表',
api: listRegion,
api: lazyListRegion,
rowKey: 'id',
columns,
formConfig: {
@ -89,7 +89,7 @@ @@ -89,7 +89,7 @@
function onExpandClick(expanded, info) {
if (expanded) {
setLoading(true);
listRegion({ parentId: info.id }).then(res => {
lazyListRegion({ parentId: info.id }).then(res => {
info.children = res;
setLoading(false);
}).catch(() => setLoading(false));

4
src/views/system/user/UserModal.vue

@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
import { BasicForm, useForm } from '/@/components/Form/index';
import { userFormSchema } from './user.data';
import { listDept } from '/@/api/platform/system/controller/dept';
import { addUser, editUserRole, getUser } from '/@/api/platform/system/controller/user';
import { addUser, editUser, getUser } from '/@/api/platform/system/controller/user';
import { listToTree } from '/@/utils/helper/treeHelper';
import { ModalProps } from '/@/components/Modal';
import { findListNameById } from '/@/utils';
@ -101,7 +101,7 @@ @@ -101,7 +101,7 @@
await addUser(formData);
break;
case 'edit':
await editUserRole(formData);
await editUser(formData);
break;
}
//

2
src/views/system/user/account/setting/UserInfo.vue

@ -104,7 +104,7 @@ @@ -104,7 +104,7 @@
}
function handleAvatarChange({ src, data }) {
state.userInfo.avatar = data.url;
state.userInfo.avatar = data.availablePath;
}
return {

Loading…
Cancel
Save