Commit 24852213 authored by sixiaofeng's avatar sixiaofeng

1

parent bab00865
This diff is collapsed.
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
"autoprefixer": "^9.8.6", "autoprefixer": "^9.8.6",
"babel-plugin-import": "^1.13.3", "babel-plugin-import": "^1.13.3",
"compression-webpack-plugin": "^6.1.1", "compression-webpack-plugin": "^6.1.1",
"cropperjs": "^1.5.12",
"eslint": "^6.7.2", "eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2", "eslint-plugin-vue": "^6.2.2",
"less": "^3.0.4", "less": "^3.0.4",
......
...@@ -6,14 +6,14 @@ ...@@ -6,14 +6,14 @@
<div class="header-wrapper fixed top-0 left-0 w-screen z-50" :class="headerBg"> <div class="header-wrapper fixed top-0 left-0 w-screen z-50" :class="headerBg">
<div class="header relative flex justify-center items-center py-3 h-12"> <div class="header relative flex justify-center items-center py-3 h-12">
<div class="h-action-wrapper absolute left-3 top-1/2 transform -translate-y-1/2 flex justify-center items-center"> <div class="h-action-wrapper absolute left-3 top-1/2 transform -translate-y-1/2 flex justify-center items-center">
<template v-if="leftArrow"> <div v-if="leftArrow">
<app-icon <app-icon
type="png" type="png"
class-name="w-6.5 w-6.5" class-name="w-6.5 w-6.5"
icon-name="left-arrow" icon-name="left-arrow"
@click="clickLeft" @click="clickLeft"
/> />
</template> </div>
<slot name="left" /> <slot name="left" />
</div> </div>
<div <div
......
...@@ -22,7 +22,8 @@ export interface AcceptJoinDTO{ ...@@ -22,7 +22,8 @@ export interface AcceptJoinDTO{
"hash": string, "hash": string,
"joinTime": number, "joinTime": number,
"phone": string, "phone": string,
"position": string "position": string,
"shortPhone"?: string
} }
export interface CreateEnterpriseDTO { export interface CreateEnterpriseDTO {
...@@ -116,15 +117,17 @@ export interface ResignDTO { ...@@ -116,15 +117,17 @@ export interface ResignDTO {
} }
export interface UpdateStaffDTO { export interface UpdateStaffDTO {
"id": string,
"depId": string, "depId": string,
"email": string, "email"?: string,
"phone": string, "phone": string,
"position": string, "position": string,
"entId": string, "entId": string,
"jionTime": number, "joinTime": number,
"leaderId": string, "leaderId"?: string,
"name": string, "name": string,
"workplace"?: string "workplace"?: string,
"shortPhone"?: string
} }
// 审核 // 审核
......
...@@ -36,7 +36,8 @@ enum BridgeMethods { ...@@ -36,7 +36,8 @@ enum BridgeMethods {
GEN_JOIN_FORM = 'genJoinForm', GEN_JOIN_FORM = 'genJoinForm',
SIGN = 'sign', SIGN = 'sign',
GET_PUBLIC_KEY = 'getPublicKey', GET_PUBLIC_KEY = 'getPublicKey',
REFRESH_COMPANY_STATE = 'refreshCompanyState' REFRESH_COMPANY_STATE = 'refreshCompanyState',
Close = 'close'
} }
export function isAppEnv() { export function isAppEnv() {
...@@ -103,6 +104,17 @@ export function goBack() { ...@@ -103,6 +104,17 @@ export function goBack() {
} }
/** /**
* 用于导航
* @returns
*/
export function close() {
const data = dsbridge.call(BridgeMethods.Close, {}, (res) => {
return res
})
return data
}
/**
* 企业联系人详情页面 * 企业联系人详情页面
* @returns * @returns
*/ */
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/> />
<!-- 通讯录 --> <!-- 通讯录 -->
<div class="pb-16"> <div class="pb-16">
<div class="text-text-secondary py-1"></div> <div class="text-text-secondary py-1">管理</div>
<team-contacts <team-contacts
:radio="showRadio" :radio="showRadio"
:checked.sync="checkedMemberId" :checked.sync="checkedMemberId"
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/> />
<!-- 通讯录 --> <!-- 通讯录 -->
<div class="pb-16"> <div class="pb-16">
<div class="text-text-secondary py-1"></div> <div class="text-text-secondary py-1">管理</div>
<team-contacts <team-contacts
:radio="showRadio" :radio="showRadio"
:checked.sync="checkedMemberId" :checked.sync="checkedMemberId"
......
...@@ -6,13 +6,18 @@ ...@@ -6,13 +6,18 @@
:ent-id="entId" :ent-id="entId"
:selected.sync="selectedDepId" :selected.sync="selectedDepId"
/> />
<main-page left-arrow :loading="loading" @click-left="handleClickLeft"> <main-page
<template #right> left-arrow
:loading="loading"
:title="pageTitle"
@click-left="handleClickLeft"
>
<template #right v-if="!isEdit">
<div class="text-color-primary" @click="$router.push({ name: 'Import' })"> <div class="text-color-primary" @click="$router.push({ name: 'Import' })">
批量导入 批量导入
</div> </div>
</template> </template>
<div class="px-4 pt-14 pb-16"> <div class="px-4 pt-14 pb-6">
<!-- 姓名/职位 --> <!-- 姓名/职位 -->
<input-cell <input-cell
v-model="acceptJoin.name" v-model="acceptJoin.name"
...@@ -41,12 +46,12 @@ ...@@ -41,12 +46,12 @@
type="input" type="input"
:validator="checkPhone" :validator="checkPhone"
/> />
<!-- <c-cell <c-cell
v-model="digit" v-model="acceptJoin.shortPhone"
title="员工编号" title="号"
placeholder="请输入员工编号" placeholder="请输入号"
type="input" type="input"
/>--> />
<c-cell <c-cell
v-model="date" v-model="date"
dot dot
...@@ -67,9 +72,23 @@ ...@@ -67,9 +72,23 @@
<group-cell required class="mt-4" title="所属部门" @click.native="selectDep"> <group-cell required class="mt-4" title="所属部门" @click.native="selectDep">
<c-cell dot :title="currentDep.name" /> <c-cell dot :title="currentDep.name" />
</group-cell> </group-cell>
<group-cell class="mt-4" title="绑定账户">
<c-cell
v-model="usrId"
class-input="text-left"
placeholder="请输入账户ID"
type="input"
/>
</group-cell>
<!--按钮--> <!--按钮-->
<div class="fixed bottom-0 left-0 w-full px-4 py-1.5 bg-common-bg"> <div class="mt-4">
<c-button @click="generateQrCode">生成邀请二维码</c-button> <div v-if="!isEdit">
<c-button @click="generateQrCode">生成邀请二维码</c-button>
</div>
<div v-else>
<c-button @click="save">保存</c-button>
<c-button class="mt-2" type="secondary" @click="deleteUsr">删除员工</c-button>
</div>
</div> </div>
</div> </div>
</main-page> </main-page>
...@@ -80,12 +99,10 @@ ...@@ -80,12 +99,10 @@
import Vue from 'vue' import Vue from 'vue'
import { Calendar, Overlay } from 'vant' import { Calendar, Overlay } from 'vant'
import { AcceptJoinDTO } from '@/service/moudles/service.dto' import { AcceptJoinDTO, UpdateStaffDTO } from '@/service/moudles/service.dto'
import { trim } from '@/util/Contact' import { trim } from '@/util/Contact'
import { Department } from '@/Interface' import { Department } from '@/Interface'
import { useLocalStorageState } from 'ahooks-vue'
import { formatDate } from '@/util/FormatDate' import { formatDate } from '@/util/FormatDate'
import DepSelector from '@/views/team/components/dep-selector.vue'
import { getPublicKey, getSign, getUserInfo } from '@/util/Bridge' import { getPublicKey, getSign, getUserInfo } from '@/util/Bridge'
Vue.use(Calendar).use(Overlay) Vue.use(Calendar).use(Overlay)
...@@ -124,7 +141,8 @@ export default Vue.extend({ ...@@ -124,7 +141,8 @@ export default Vue.extend({
hash: '', hash: '',
joinTime: Math.round(new Date().getTime()/1000), joinTime: Math.round(new Date().getTime()/1000),
phone: '', phone: '',
position: '' position: '',
shortPhone: ''
} }
return { return {
formatDate, formatDate,
...@@ -136,20 +154,111 @@ export default Vue.extend({ ...@@ -136,20 +154,111 @@ export default Vue.extend({
currentDep, currentDep,
loading: false, loading: false,
acceptJoin, acceptJoin,
updateStaff: {} as UpdateStaffDTO,
showDepSelector: false, showDepSelector: false,
depTree depTree,
pageTitle: '添加成员',
isEdit: false,
usrId: '',
shortPhone: ''
} }
}, },
async created() { async created() {
const entInfo = JSON.parse(localStorage.getItem('ENT_INFO') || '{}') const query = this.$route.query
this.entId = entInfo.id || '168398222891421696' if (query.edit === '1') {
this.selectedDepId = this.depId = this.$route.query.id as string || entInfo.rootDepId // 编辑
// this.acceptJoin = Object.assign(this.acceptJoin, this.$store.state.acceptJoin) this.isEdit = true
this.pageTitle = '编辑成员'
this.usrId = query.usrId
const usrInfo = await this.getStaff(this.usrId)
this.selectedDepId = this.depId = usrInfo.depId
this.entId = usrInfo.entId
this.date = this.formatDate(usrInfo.joinTime)
this.acceptJoin = Object.assign({}, this.acceptJoin, usrInfo)
} else {
// 添加
const entInfo = JSON.parse(localStorage.getItem('ENT_INFO') || '{}')
this.selectedDepId = this.depId = this.$route.query.id as string || entInfo.rootDepId
this.entId = entInfo.id || '168398222891421696'
this.date = this.formatDate(new Date())
this.pageTitle = '添加成员'
}
const dep = await this.getSub(this.depId) const dep = await this.getSub(this.depId)
this.currentDep = dep.dep this.currentDep = dep.dep
this.date = this.formatDate(new Date())
}, },
methods: { methods: {
validateParmas(): boolean {
const {phone, name, position, joinTime} = this.acceptJoin
return !this.validatePhone(phone) || trim(name) === '' || trim(position) === '' || joinTime === 0 || trim(this.depId) === ''
},
getStaff(id: string) {
this.loading = true
return this.$service.staff.getInfo({
id: this.usrId
}).then((res: any) => {
this.loading = false
const {data} = res
if (data.code === this.$global.success) {
return data.data
} else {
this.$toast(data.msg)
}
})
},
deleteUsr() {
this.$dialog.confirm({
title: '提示',
message: '移出成员后,将移出对应的部门群,若是主管,则对应部门群群主将随机抽取群管理员或群内成员临时担任,确定移出吗?'
// confirmButtonText: '解散'
}).then(() => {
this.loading = true
this.$service.staff.resign({
entId: this.entId,
id: this.usrId
}).then((res: any) => {
this.loading = false
const {data} = res
if (data.code === this.$global.success) {
this.$toast('删除成功')
this.$router.replace('/team/team-frame')
} else {
this.$toast(data.msg)
}
}).catch(() => this.loading=false)
}).catch(() => {
console.log('删除')
})
},
save() {
if (this.validateParmas()) {
this.$toast('请检查输入内容')
return
}
const {depId, entId, joinTime, name, phone, position, shortPhone} = this.acceptJoin
this.updateStaff = {
depId,
entId,
joinTime,
name,
phone,
position,
id: this.usrId,
leaderId: this.currentDep.leaderId,
shortPhone
}
console.log(this.updateStaff, 'update')
this.loading = true
this.$service.staff.updateInfo(this.updateStaff).then((res: any) => {
this.loading = false
const {data} = res
if (data.code === this.$global.success) {
this.$toast('更新成功')
this.$router.replace('/team/team-frame')
} else {
this.$toast(data.msg)
}
}).catch(()=>this.loading=false)
},
async selectDep() { async selectDep() {
const parentId = JSON.parse(localStorage.getItem('ENT_INFO') as string).rootDepId const parentId = JSON.parse(localStorage.getItem('ENT_INFO') as string).rootDepId
const dep = await this.getSub(parentId) const dep = await this.getSub(parentId)
...@@ -182,6 +291,8 @@ export default Vue.extend({ ...@@ -182,6 +291,8 @@ export default Vue.extend({
this.loading = false this.loading = false
if (data.code === this.$global.success) { if (data.code === this.$global.success) {
this.currentDep = data.data this.currentDep = data.data
} else {
this.$toast(data.msg)
} }
}) })
}, },
...@@ -206,7 +317,7 @@ export default Vue.extend({ ...@@ -206,7 +317,7 @@ export default Vue.extend({
this.date = this.formatDate(date) this.date = this.formatDate(date)
}, },
generateQrCode() { generateQrCode() {
if (!this.validatePhone(this.acceptJoin.phone) || trim(this.acceptJoin.name) === '' || trim(this.acceptJoin.position) === '' || this.acceptJoin.joinTime === 0 || trim(this.depId) === '') { if (this.validateParmas()) {
this.$toast('请检查输入内容') this.$toast('请检查输入内容')
return return
} }
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
<member-selector <member-selector
:show.sync="showMemberSelector" :show.sync="showMemberSelector"
:show-team="true" :show-team="true"
:multiple="true" :multiple="multiple"
title="添加管理员" :title="selectorTitle"
:checked-member-id.sync="selectedLeaderId" :checked-member-id.sync="selectedLeaderId"
@confirm="confirmAdd" @confirm="confirm"
/> />
<div class="px-4 pt-14"> <div class="px-4 pt-14">
<div class="bg-white rounded px-4"> <div class="bg-white rounded px-4">
...@@ -97,7 +97,9 @@ export default Vue.extend({ ...@@ -97,7 +97,9 @@ export default Vue.extend({
loading: false, loading: false,
entInfo: {} as LocalStoreEnt, entInfo: {} as LocalStoreEnt,
leaderList: [] as Staff[], leaderList: [] as Staff[],
adminList: [] as Staff[] adminList: [] as Staff[],
multiple: false,
selectorTitle: ''
} }
}, },
mounted() { mounted() {
...@@ -106,7 +108,7 @@ export default Vue.extend({ ...@@ -106,7 +108,7 @@ export default Vue.extend({
}, },
methods: { methods: {
// 添加管理员 // 添加管理员
confirmAdd(arr: string[]) { confirm(arr: string[]) {
console.log(arr, 'arr') console.log(arr, 'arr')
const requests = [] as any[] const requests = [] as any[]
if (arr.length === 0) return if (arr.length === 0) return
...@@ -157,8 +159,19 @@ export default Vue.extend({ ...@@ -157,8 +159,19 @@ export default Vue.extend({
} }
}).catch(() => this.loading = false) }).catch(() => this.loading = false)
}, },
removeManager(id: number | string) { removeManager(id: string) {
// this.list = this.list.filter(item => item.id !== id) // this.list = this.list.filter(item => item.id !== id)
this.loading = true
this.changeRole(id, 3).then((res: any) => {
const {data} = res
this.loading = false
if (data.code === this.$global.success) {
// 转让成功
this.$router.replace('/team/team-frame')
} else {
this.$toast(data.msg)
}
}).catch(() => this.loading = false)
}, },
addManager() { addManager() {
this.selectedLeaderId = [] this.selectedLeaderId = []
...@@ -166,6 +179,8 @@ export default Vue.extend({ ...@@ -166,6 +179,8 @@ export default Vue.extend({
this.selectedLeaderId.push(a.id) this.selectedLeaderId.push(a.id)
}) })
this.showMemberSelector = true this.showMemberSelector = true
this.selectorTitle = '添加管理员'
this.multiple = true
} }
} }
}) })
......
<template>
<!-- 头像 -->
<div v-if="show" class="min-h-screen w-full border relative z-2001 bg-black px-4">
<van-action-sheet
v-model="showActionSheet"
:actions="actions"
cancel-text="取消"
close-on-click-action
@select="onSelect"
/>
<div class="header h-12 flex items-center justify-between">
<app-icon
class-name="w-6.5 h-6.5"
icon-name="left-arrow-white"
@click="goBack"
/>
<div class="text-white">团队头像</div>
<app-icon
class-name="w-5 h-1"
icon-name="dot-h"
@click="showActionSheet=true"
/>
</div>
<!-- 默认头像 -->
<div v-if="showDefault" class="default-avator mt-4 rounde overflow-hidden mx-auto mt-4">
<img :src="defaultImg" alt="">
<c-button class="mt-4" @click="saveImage">保存</c-button>
</div>
<!-- 裁剪图片 -->
<div v-if="showCropper">
<div class="before"></div>
<!-- <div class="w-screnn h-screnn bg-center" > -->
<img :src="img" alt="" class="" ref="image">
<c-button class="mt-4" @click="saveCropper">保存</c-button>
</div>
<!-- 拍照 -->
<div v-if="showCamera">
<video class="video-view" ref="video" autoplay playsinline="true" webkit-playsinline="true" />
<canvas ref="canvas" :width="cameraWidth" :height="cameraHeight" style="display: none"></canvas>
<c-button class="mt-4" @click="saveImg">拍照</c-button>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import Cropper from "cropperjs"
import "cropperjs/dist/cropper.css"
export default Vue.extend({
name: 'AvatorEditor',
components: {
'app-icon':()=>import('@/components/common/Icon.vue'),
'main-page': () => import('@/layout/main-page.vue'),
'c-cell': () => import('@/components/common/c-cell.vue'),
'c-button': () => import('@/components/common/c-button.vue'),
'input-cell': () => import('@/components/common/input-cell.vue')
},
props: {
imgSrc: String,
show: Boolean
},
data() {
return {
cameraWidth: 0,
cameraHeight: 0,
stream: {} as any,
myCropper: {} as Cropper,
showActionSheet: false,
// showVideo: false,
showCropper: false,
showCamera: false,
showDefault: true,
img: '',
actions: [
{name: '拍照', action: 'photo'},
{name: '从手机相册选择', action: 'file'}
],
defaultImg: require('@/assets/qrcode.png')
}
},
watch: {
imgSrc(val: string) {
this.defaultImg = val
}
},
methods: {
goBack() {
this.$emit('update:show', false)
},
onSelect(item: {name: string, action: string}) {
if (item.action === 'photo') {
this.showCamera = true
this.showDefault = false
// this.showVideo=true
this.$nextTick(() => {
this.openCamera()
})
}
},
// 保存头像
saveImage() {
// this.showAvator = false
this.$emit('update:img-src', this.defaultImg)
this.$emit('update:show', false)
},
openCamera() {
if (
(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) ||
navigator.getUserMedia ||
(navigator as any).webkitGetUserMedia ||
(navigator as any).mozGetUserMedia
) {
//调用用户媒体设备,访问摄像头
this.initVideo({
video: {
height: 800,
// facingMode: "user",
facingMode: {
// 强制后置摄像头
exact: "user",
// exact: "environment",
},
},
})
} else {
alert("你的浏览器不支持访问用户媒体设备")
}
},
initCropper() {
this.myCropper = new Cropper(this.$refs.image as HTMLImageElement, {
viewMode: 1,
dragMode: 'none',
initialAspectRatio: 1,
aspectRatio: 1,
preview: '.before',
background: false,
autoCropArea: 0.6,
zoomOnWheel: false,
})
console.log(this.myCropper, 'sds')
},
initVideo(constrains: any) {
let _this = this
if (navigator.mediaDevices.getUserMedia) {
//最新标准API
navigator.mediaDevices
.getUserMedia(constrains)
.then(_this.videoSuccess)
.catch(_this.videoError)
} else if ((navigator as any).webkitGetUserMedia) {
//webkit内核浏览器
(navigator as any)
.webkitGetUserMedia(constrains)
.then(_this.videoSuccess)
.catch(_this.videoError)
} else if ((navigator as any).mozGetUserMedia) {
//Firefox浏览器
(navigator as any)
.mozGetUserMedia(constrains)
.then(_this.videoSuccess)
.catch(_this.videoError)
} else if ((navigator as any).getUserMedia) {
//旧版API
(navigator as any)
.getUserMedia(constrains)
.then(_this.videoSuccess)
.catch(_this.videoError)
}
},
videoSuccess(stream: any) {
let video = this.$refs.video as HTMLVideoElement,
_this = this
//将视频流设置为video元素的源
video.srcObject = stream
//播放视频
video.play()
video.oncanplay = function () {
// 摄像头分辨率,手机480x640
console.log("摄像头分辨率")
console.log(video.videoWidth, video.videoHeight)
_this.cameraWidth = video.videoWidth
_this.cameraHeight = video.videoHeight
// 发送图片进行识别
// _this.readImg()
}
this.stream = stream
},
// 保存截图
saveCropper() {
const imgData = this.myCropper.getCroppedCanvas({
imageSmoothingQuality: 'high'
}).toDataURL('image/png')
this.defaultImg = imgData
this.showDefault = true
this.showCropper = false
},
saveImg() {
this.readImg()
this.stream.getTracks().forEach(function(track: any){
track.stop()
})
this.showCamera = false
this.showCropper = true
this.$nextTick(() => {
this.initCropper()
})
},
readImg() {
let video = this.$refs.video as HTMLVideoElement,
canvas = this.$refs.canvas as HTMLCanvasElement,
// canvas.style
context = canvas.getContext("2d") as CanvasRenderingContext2D,
_this = this
// let timer = setInterval(function () {
context.drawImage(
video,
0,
0,
_this.cameraWidth,
_this.cameraHeight,
0,
0,
_this.cameraWidth,
_this.cameraHeight,
)
// 扫码条形码
let imgUri = canvas.toDataURL()
this.img = imgUri
},
videoError(error: Error) {
console.log("访问用户媒体设备失败:", error.name, error.message)
}
}
})
</script>
<style lang="less" scoped>
/deep/ .cropper-container {
width: 100% !important
}
.default-avator {
min-width: 60vw;
min-height: 60vw;
// border: 1px solid red;
}
</style>
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
<!-- <div class="py-2">{{currentDep.name}}</div> --> <!-- <div class="py-2">{{currentDep.name}}</div> -->
<!-- 通讯录 --> <!-- 通讯录 -->
<div class="pb-16"> <div class="pb-16">
<div class="text-text-secondary py-1">成员</div> <!-- <div class="text-text-secondary py-1">成员</div> -->
<team-contacts <team-contacts
container-id="member-selector" container-id="member-selector"
:leader="leaders" :leader="leaders"
...@@ -105,7 +105,6 @@ export default Vue.extend({ ...@@ -105,7 +105,6 @@ export default Vue.extend({
name: '', name: '',
parentId: '' parentId: ''
} }
let changedVal: Array<string> = []
return { return {
tree, tree,
teamArr: [] as Department[], teamArr: [] as Department[],
...@@ -125,6 +124,11 @@ export default Vue.extend({ ...@@ -125,6 +124,11 @@ export default Vue.extend({
this.entId = JSON.parse(localStorage.getItem('ENT_INFO') || '{}').id this.entId = JSON.parse(localStorage.getItem('ENT_INFO') || '{}').id
this.getEntInfo() this.getEntInfo()
}, },
computed: {
isNotDepRoot():boolean {
return this.currentDep.parentId !== '-1'
},
},
methods: { methods: {
goPre(dep: Department) { goPre(dep: Department) {
this.parentId = dep.id this.parentId = dep.id
...@@ -192,9 +196,15 @@ export default Vue.extend({ ...@@ -192,9 +196,15 @@ export default Vue.extend({
const { data } = res const { data } = res
this.loading = false this.loading = false
if (data.code === this.$global.success) { if (data.code === this.$global.success) {
// this.currentDep = data.data.dep this.currentDep = data.data.dep
// 负责人/管理员 // 负责人/管理员
this.leaders.list = data.data.staffList?.filter((i: Staff) => i.role !== 3) if (this.isNotDepRoot) {
// 不在架构根目录
const leader = {...data.data.leader, isDepAdmin: true}
this.leaders.list = [leader]
} else {
this.leaders.list = data.data.staffList?.filter((i: Staff) => i.role !== 3)
}
// 普通成员 // 普通成员
this.contacts = data.data.staffList?.filter((i: Staff) => i.role === 3) this.contacts = data.data.staffList?.filter((i: Staff) => i.role === 3)
// 部门树 // 部门树
......
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
{{ nav }} {{ nav }}
</div> </div>
</div> </div>
<template v-if="Object.keys(list).length > 0 || leader.list && leader.list.length > 0"> <template v-if="Object.keys(list).length > 0 || (leader.list && leader.list.length > 0)">
<!-- 主管负责人 --> <!-- 主管负责人 -->
<div class="leaders" v-if="leader.list.length > 0"> <div class="leaders" v-if="leader.list.length > 0">
<div class="text-text-secondary py-1">管理员</div>
<div <div
v-for="(l, index) in leader.list" v-for="(l, index) in leader.list"
:key="index" :key="index"
...@@ -45,6 +46,7 @@ ...@@ -45,6 +46,7 @@
</div> </div>
<!-- 成员 --> <!-- 成员 -->
<div class="members"> <div class="members">
<div class="text-text-secondary py-1">成员</div>
<div <div
v-for="(value, key) in list" v-for="(value, key) in list"
:key="key" :key="key"
......
...@@ -122,10 +122,9 @@ export default Vue.extend({ ...@@ -122,10 +122,9 @@ export default Vue.extend({
this.loading = true this.loading = true
const {depId,entId,expiration,hash,inviterId,joinTime,name,oaServer,phone,position} = this.info as AcceptJoinDTO const {depId,entId,expiration,hash,inviterId,joinTime,name,oaServer,phone,position} = this.info as AcceptJoinDTO
let req = { let req = {
depId,entId,expiration: Number(expiration) ,hash,inviterId,joinTime: Number(joinTime),name,oaServer,phone,position depId,entId,expiration: Number(expiration) ,hash,inviterId,joinTime: Number(joinTime),name,oaServer,phone,position
} }
console.log(this.info); console.log(this.info);
this.$service.enterprise.acceptJoin(req) this.$service.enterprise.acceptJoin(req)
.then(async (res: any) => { .then(async (res: any) => {
const {data} = res const {data} = res
......
...@@ -12,16 +12,27 @@ ...@@ -12,16 +12,27 @@
main-bg="bg-white" main-bg="bg-white"
header-bg="bg-white" header-bg="bg-white"
:loading="loading" :loading="loading"
left-arrow
@click-left="goBack"
> >
<template slot="right"> <div v-if="!isEdit" slot="left">
<app-icon <app-icon
type="png" class-name="w-6.5 h-6.5"
class-name="w-5 h-1" icon-name="home"
icon-name="dot-h-black" @click="close"
@click="showActionSheet=true"
/> />
</div>
<template slot="right">
<div v-if="!isEdit">
<app-icon
class-name="w-5 h-1"
icon-name="dot-h-black"
@click="showActionSheet=true"
/>
</div>
<div
v-else
class="text-color-primary"
@click="isEdit=false"
>取消</div>
</template> </template>
<div class="px-4 pt-14"> <div class="px-4 pt-14">
<!-- 团队架构详情 --> <!-- 团队架构详情 -->
...@@ -39,8 +50,10 @@ ...@@ -39,8 +50,10 @@
/> />
<!-- 通讯录 --> <!-- 通讯录 -->
<div class="pb-16"> <div class="pb-16">
<div class="text-text-secondary py-1">成员</div> <!-- <div class="text-text-secondary py-1">成员</div> -->
<team-contacts <team-contacts
:radio="isEdit"
:multiple="multiple"
:leader="leaders" :leader="leaders"
:checked.sync="checkedMemberId" :checked.sync="checkedMemberId"
:contact-list="commonMember" :contact-list="commonMember"
...@@ -49,7 +62,10 @@ ...@@ -49,7 +62,10 @@
</div> </div>
<!-- 底部操作 --> <!-- 底部操作 -->
<div class="py-2 px-4 bg-white w-screen fixed bottom-0 left-0 z-30" v-if="showBottomBtn"> <div class="py-2 px-4 bg-white w-screen fixed bottom-0 left-0 z-30" v-if="showBottomBtn">
<div class="grid gap-2.5" :class="isNotDepRoot ? 'grid-cols-3' : 'grid-cols-2'"> <div v-if="isEdit">
<c-button @click="confirmEdit">确定</c-button>
</div>
<div v-else class="grid gap-2.5" :class="isNotDepRoot ? 'grid-cols-3' : 'grid-cols-2'">
<c-button round @click="addMember">添加成员</c-button> <c-button round @click="addMember">添加成员</c-button>
<c-button round @click="addDep">添加部门</c-button> <c-button round @click="addDep">添加部门</c-button>
<c-button round @click="setDepartment" v-if="isNotDepRoot">部门设置</c-button> <c-button round @click="setDepartment" v-if="isNotDepRoot">部门设置</c-button>
...@@ -62,7 +78,7 @@ ...@@ -62,7 +78,7 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue' import Vue from 'vue'
import { getUserInfo, goBack, openCompanyUserInfo } from '@/util/Bridge' import { getUserInfo, close, openCompanyUserInfo } from '@/util/Bridge'
import { Department, Staff } from '@/Interface' import { Department, Staff } from '@/Interface'
import { ActionSheet } from 'vant' import { ActionSheet } from 'vant'
import { Role } from '@/service/moudles/service.dto' import { Role } from '@/service/moudles/service.dto'
...@@ -105,20 +121,22 @@ export default Vue.extend({ ...@@ -105,20 +121,22 @@ export default Vue.extend({
leaders: {} as { list: Staff[], title?: string }, leaders: {} as { list: Staff[], title?: string },
commonMember: [] as Staff[], commonMember: [] as Staff[],
teamArr: [] as Department[], teamArr: [] as Department[],
showActionSheet: false showActionSheet: false,
isEdit: false,
multiple: false
} }
}, },
async mounted() { async mounted() {
const userInfoDev = { // const userInfoDev = {
depId: '168398222891421697', // depId: '168398222891421697',
entId: '168398222891421696', // entId: '168398222891421696',
id: '1K7cApKbEU9h5WySPVLNgdSd67i2XkSuoS', // id: '1K7cApKbEU9h5WySPVLNgdSd67i2XkSuoS',
joinTime: 1631090065, // joinTime: 1631090065,
name: '徐丹', // name: '徐丹',
role: 0 // role: 0
} // }
localStorage.setItem('USR_INFO', getUserInfo() || JSON.stringify(userInfoDev)) localStorage.setItem('USR_INFO', getUserInfo())
const usrInfo = process.env.NODE_ENV==='production' ? JSON.parse(getUserInfo() || "{}") : userInfoDev const usrInfo = process.env.NODE_ENV==='production' ? JSON.parse(getUserInfo() || "{}") : {}
this.role = usrInfo.role this.role = usrInfo.role
this.entId = process.env.NODE_ENV==='production'?usrInfo.entId : '168398222891421696' this.entId = process.env.NODE_ENV==='production'?usrInfo.entId : '168398222891421696'
this.getEntInfo() this.getEntInfo()
...@@ -132,8 +150,11 @@ export default Vue.extend({ ...@@ -132,8 +150,11 @@ export default Vue.extend({
return this.role === Role.SUPER_ADMIN || this.role === Role.LEADER return this.role === Role.SUPER_ADMIN || this.role === Role.LEADER
}, },
actions() { actions() {
if (this.role === Role.LEADER) { if ([Role.LEADER, Role.SUPER_ADMIN].indexOf(this.role) > -1) {
return [{name: '管理团队', action: 'manage'}] return [
{name: '编辑成员', action: 'edit'},
{name: '管理团队', action: 'manage'}
]
} }
return [{name: '退出团队', action: 'quit'}] return [{name: '退出团队', action: 'quit'}]
} }
...@@ -144,7 +165,20 @@ export default Vue.extend({ ...@@ -144,7 +165,20 @@ export default Vue.extend({
this.$router.push('/team/team-management') this.$router.push('/team/team-management')
return return
} }
if (item.action === 'edit') {
this.isEdit = true
}
},
confirmEdit() {
if (this.checkedMemberId.length === 0) return
const id = this.checkedMemberId[0]
this.$router.push({
path: '/team/add-member',
query: {
usrId: id,
edit: '1'
}
})
}, },
// 点击面包屑上一级部门 // 点击面包屑上一级部门
goPre(dep: Department) { goPre(dep: Department) {
...@@ -152,7 +186,7 @@ export default Vue.extend({ ...@@ -152,7 +186,7 @@ export default Vue.extend({
this.getStaff() this.getStaff()
}, },
// 返回原生页面 // 返回原生页面
goBack, close,
// 获取企业信息 // 获取企业信息
getEntInfo() { getEntInfo() {
this.loading = true this.loading = true
...@@ -187,6 +221,7 @@ export default Vue.extend({ ...@@ -187,6 +221,7 @@ export default Vue.extend({
this.contacts = data.data.staffList || [] this.contacts = data.data.staffList || []
// 负责人/管理员 // 负责人/管理员
if (this.isNotDepRoot) { if (this.isNotDepRoot) {
// 不在架构根目录
const leader = {...data.data.leader, isDepAdmin: true} const leader = {...data.data.leader, isDepAdmin: true}
this.leaders.list = [leader] this.leaders.list = [leader]
} else { } else {
......
...@@ -34,9 +34,9 @@ ...@@ -34,9 +34,9 @@
/> />
<!-- <van-uploader :after-read="afterRead" /> --> <!-- <van-uploader :after-read="afterRead" /> -->
</div> </div>
<!-- <div class="fixed bottom-0 left-0 w-full px-4 py-2"> <div class="fixed bottom-0 left-0 w-full px-4 py-2">
<c-button round @click="$router.go(-1)">确定</c-button> <c-button round @click="$router.go(-1)">确定</c-button>
</div> --> </div>
</main-page> </main-page>
</template> </template>
......
...@@ -4,46 +4,97 @@ ...@@ -4,46 +4,97 @@
left-arrow left-arrow
@click-left="$router.go(-1)" @click-left="$router.go(-1)"
> >
<avator-editor
:show.sync="showEditor"
:img-src.sync="defaultImg"
/>
<div class="px-4 pt-14"> <div class="px-4 pt-14">
<c-cell <c-cell
dot dot
title="团队头像" title="团队头像"
@click="$router.push('/team/team-avator')" @click="showEditor=true"
> >
<template slot="right"> <template slot="right">
<div class="w-7 h-7 rounded overflow-hidden flex items-center justify-center"> <div class="w-7 h-7 rounded overflow-hidden flex items-center justify-center">
<img class="max-w-full" src="@/assets/images/33.png" alt=""> <img class="max-w-full" :src="defaultImg" alt="">
</div> </div>
</template> </template>
</c-cell> </c-cell>
<c-cell <input-cell
dot class="mt-4"
title="团队名称" v-model="updateInfo.name"
content="杭州复杂美科技有限公司" required
@click="$router.push('/team/team-name')" :limit="20"
label="团队名称"
placeholder="请输入团队名称"
error-msg="团队名称为空"
/>
<input-cell
class="mt-4"
v-model="updateInfo.description"
:limit="300"
required
type="textarea"
label="团队描述"
placeholder="请输入团队描述"
/> />
<c-cell dot title="团队描述" @click="$router.push('/team/team-description')" /> <c-button class="mt-4">保存</c-button>
</div> </div>
</main-page> </main-page>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue' import Vue from 'vue'
import {updateEnterpriseDTO} from '@/service/moudles/service.dto'
// import Cropper from "cropperjs"
// import "cropperjs/dist/cropper.css"
import {ActionSheet} from 'vant'
Vue.use(ActionSheet)
export default Vue.extend({ export default Vue.extend({
name: 'TeamInfo', name: 'TeamInfo',
components: { components: {
// 'app-icon':()=>import('@/components/common/Icon.vue'), 'app-icon':()=>import('@/components/common/Icon.vue'),
'main-page': () => import('@/layout/main-page.vue'), 'main-page': () => import('@/layout/main-page.vue'),
'c-cell': () => import('@/components/common/c-cell.vue') 'c-cell': () => import('@/components/common/c-cell.vue'),
'c-button': () => import('@/components/common/c-button.vue'),
'input-cell': () => import('@/components/common/input-cell.vue'),
'avator-editor': () => import('@/views/team/components/avator-editor.vue')
}, },
data() { data() {
return {} return {
updateInfo: {} as updateEnterpriseDTO,
showActionSheet: false,
defaultImg: require('@/assets/qrcode.png'),
showEditor: false
}
},
mounted() {
}, },
methods: {} methods: {
// onSelect(item: {name: string, action: string}) {
// if (item.action === 'photo') {
// this.showCamera = true
// this.showDefault = false
// // this.showVideo=true
// this.$nextTick(() => {
// this.openCamera()
// })
// }
// }
}
}) })
</script> </script>
<style lang="less"> <style lang="less" scoped>
/deep/ .cropper-container {
width: 100% !important
}
.default-avator {
min-width: 60vw;
min-height: 60vw;
// border: 1px solid red;
}
</style> </style>
...@@ -16,13 +16,21 @@ ...@@ -16,13 +16,21 @@
class-name="h-4 w-4 inline-block ml-1" class-name="h-4 w-4 inline-block ml-1"
/> />
</div> </div>
<div class="h-6.5 w-6.5 flex items-center justify-end"> <!-- <div class="h-6.5 w-6.5 flex items-center justify-end">
<app-icon <app-icon
icon-name="code" icon-name="code"
class-name="w-4 h-4" class-name="w-4 h-4"
/> />
</div> </div> -->
</template> </template>
<member-selector
:show.sync="showMemberSelector"
:show-team="true"
:multiple="multiple"
:title="selectorTitle"
:checked-member-id.sync="selectedLeaderId"
@confirm="confirm"
/>
<div class="px-4 pt-14"> <div class="px-4 pt-14">
<!-- 头部 --> <!-- 头部 -->
<div class="flex items-center pt-1 pb-5"> <div class="flex items-center pt-1 pb-5">
...@@ -50,7 +58,7 @@ ...@@ -50,7 +58,7 @@
<c-cell dot title="团队管理权限" :content="`共${managerNum}人`" @click="$router.push('/team/auth-management')" /> <c-cell dot title="团队管理权限" :content="`共${managerNum}人`" @click="$router.push('/team/auth-management')" />
<c-cell dot title="转让负责人" @click="transferManagement" /> <c-cell dot title="转让负责人" @click="transferManagement" />
</template> </template>
<c-cell dot title="申请管理" @click="$router.push('/team/request-management')" /> <!-- <c-cell dot title="申请管理" @click="$router.push('/team/request-management')" /> -->
</div> </div>
<c-button v-if="isLeader" round type="secondary" class="mt-16" @click="deleteTeam"> <c-button v-if="isLeader" round type="secondary" class="mt-16" @click="deleteTeam">
解散团队 解散团队
...@@ -70,13 +78,18 @@ export default Vue.extend({ ...@@ -70,13 +78,18 @@ export default Vue.extend({
'app-icon': () => import('@/components/common/Icon.vue'), 'app-icon': () => import('@/components/common/Icon.vue'),
'main-page': () => import('@/layout/main-page.vue'), 'main-page': () => import('@/layout/main-page.vue'),
'c-cell': () => import('@/components/common/c-cell.vue'), 'c-cell': () => import('@/components/common/c-cell.vue'),
'c-button': () => import('@/components/common/c-button.vue') 'c-button': () => import('@/components/common/c-button.vue'),
'member-selector': () => import('@/views/team/components/member-selector.vue')
}, },
data() { data() {
return { return {
enterpriseInfo: {} as LocalStoreEnt, enterpriseInfo: {} as LocalStoreEnt,
loading: false, loading: false,
managerNum: 0 managerNum: 0,
showMemberSelector: false,
selectorTitle: '',
multiple: false,
selectedLeaderId: [] as string[]
} }
}, },
mounted() { mounted() {
...@@ -113,13 +126,28 @@ export default Vue.extend({ ...@@ -113,13 +126,28 @@ export default Vue.extend({
console.log('edit') console.log('edit')
this.$router.push('/team/team-info') this.$router.push('/team/team-info')
}, },
transferManagement() { confirm(arr: string[]) {
this.$router.push({ if (arr.length === 0) return
path: '/team/team-frame', this.loading = true
query: { const newLeaderId = arr[0]
showRadio: '1' const id = JSON.parse(localStorage.getItem('USR_INFO') as string).id
this.$service.enterprise.updateLeader({
id,
newLeaderId
}).then((res: any) => {
this.loading = false
const {data} = res
if (data.code === this.$global.success) {
this.$router.replace('/team/team-frame')
} else {
this.$toast(data.msg)
} }
}) }).catch(() => this.loading=false)
},
transferManagement() {
this.showMemberSelector = true
this.selectorTitle = '转让负责人'
// this.selectorTitle = [this.leaderL]
}, },
deleteTeam() { deleteTeam() {
this.$dialog.confirm({ this.$dialog.confirm({
......
...@@ -144,7 +144,6 @@ export default Vue.extend({ ...@@ -144,7 +144,6 @@ export default Vue.extend({
if (window.devicePixelRatio && window.devicePixelRatio > 1) { if (window.devicePixelRatio && window.devicePixelRatio > 1) {
return window.devicePixelRatio return window.devicePixelRatio
} }
return 1 return 1
}, },
async drawCanvas(selector: string) { async drawCanvas(selector: string) {
......
...@@ -31,25 +31,25 @@ module.exports = { ...@@ -31,25 +31,25 @@ module.exports = {
} }
} }
} }
} },
// configureWebpack: { configureWebpack: {
// optimization: { optimization: {
// minimize: true, minimize: true,
// minimizer: [ minimizer: [
// new TerserPlugin({ new TerserPlugin({
// parallel: true, parallel: true,
// terserOptions: { terserOptions: {
// compress: { compress: {
// drop_console: true, // 默认false -- 移除console.*(console.log、console.error等等) drop_console: true, // 默认false -- 移除console.*(console.log、console.error等等)
// }, },
// }, },
// }), }),
// ], ],
// }, },
// plugins: [ plugins: [
// new CompressionWebpackPlugin(), new CompressionWebpackPlugin(),
// ], ],
// }, },
// pwa: { // pwa: {
// name: 'My App', // name: 'My App',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment