Files
2026-09-24 14:58:23 +08:00

84 lines
3.1 KiB
Vue

<template>
<view class="page">
<fy-header title="发起群聊" back />
<view class="card field">
<input v-model="name" placeholder="群名称(必填)" />
</view>
<view class="hint">已选 {{ picked.length }} </view>
<view class="card">
<view v-for="p in people" :key="p.id" class="item" @click="toggle(p.id)">
<view class="box" :class="{ on: picked.includes(p.id) }" />
<image v-if="p.avatar" class="av img" :src="p.avatar" mode="aspectFill" />
<view v-else class="av">{{ (p.name || '?').slice(0, 1) }}</view>
<view class="meta">
<text class="n">{{ p.name }}</text>
<text class="s">{{ p.title }} · {{ p.department }}</text>
</view>
</view>
</view>
<view class="pad">
<wd-button type="primary" block size="large" :disabled="!can" @click="ok">创建并进入</wd-button>
</view>
</view>
</template>
<script>
import FyHeader from '../../components/fy-header.vue'
import { store } from '../../utils/store.js'
import { toast } from '../../utils/format.js'
export default {
components: { FyHeader },
data() {
return { name: '', picked: [] }
},
computed: {
people() {
return Object.values(store.people).filter((p) => !store.me || p.id !== store.me.id)
},
can() {
return String(this.name || '').trim() && this.picked.length >= 1
}
},
methods: {
toggle(id) {
const i = this.picked.indexOf(id)
if (i >= 0) this.picked.splice(i, 1)
else this.picked.push(id)
},
async ok() {
if (!this.can) {
toast('请填写群名并至少选一位同事')
return
}
try {
uni.showLoading({ title: '创建中…', mask: true })
const conv = await store.createGroup(this.name.trim(), this.picked)
uni.hideLoading()
uni.redirectTo({ url: '/pages/chat/chat?sid=' + encodeURIComponent(conv.id) })
} catch (e) {
uni.hideLoading()
toast((e && e.message) || '创建失败')
}
}
}
}
</script>
<style scoped>
.field { margin: 16rpx 24rpx; padding: 8rpx 24rpx; }
.field input { height: 88rpx; font-size: 30rpx; color: #111827; }
.hint { margin: 0 32rpx 12rpx; font-size: 24rpx; color: #6B7280; }
.card { margin: 0 24rpx 24rpx; overflow: hidden; }
.item { display: flex; align-items: center; padding: 0 24rpx; }
.item + .item .meta { border-top: 1rpx solid #F0F2F5; }
.box { width: 36rpx; height: 36rpx; border: 2rpx solid #D1D5DB; border-radius: 8rpx; margin-right: 16rpx; flex-shrink: 0; }
.box.on { background: #1677FF; border-color: #1677FF; }
.av { width: 72rpx; height: 72rpx; border-radius: 18rpx; background: #E8F1FF; color: #1677FF; display: flex; align-items: center; justify-content: center; font-weight: 600; margin: 16rpx 0; flex-shrink: 0; overflow: hidden; }
.av.img { display: block; }
.meta { margin-left: 16rpx; flex: 1; min-width: 0; padding: 18rpx 0; }
.n { display: block; font-size: 28rpx; font-weight: 600; color: #111827; }
.s { display: block; margin-top: 4rpx; font-size: 22rpx; color: #6B7280; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pad { padding: 0 24rpx 40rpx; }
</style>