瑶都万能墙
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

466 lines
10 KiB

  1. <template>
  2. <view class="page">
  3. <navbar title="创建群组" bgColor="#5baaff" color="#fff" leftClick @leftClick="$utils.navigateBack" />
  4. <view class="form-container">
  5. <!-- 群组头像 -->
  6. <view class="avatar-section">
  7. <view class="avatar-title">群组头像</view>
  8. <view class="avatar-upload" @click="chooseAvatar">
  9. <image v-if="groupForm.image" :src="groupForm.image" class="avatar-preview" mode="aspectFill"></image>
  10. <view v-else class="avatar-placeholder">
  11. <uv-icon name="camera" size="60rpx" color="#ccc"></uv-icon>
  12. <text>点击上传头像</text>
  13. </view>
  14. </view>
  15. </view>
  16. <!-- 群组信息表单 -->
  17. <view class="form-section">
  18. <view class="form-item">
  19. <view class="form-label">群组名称</view>
  20. <uv-input
  21. v-model="groupForm.title"
  22. placeholder="请输入群组名称"
  23. :border="false"
  24. :clearable="true"
  25. ></uv-input>
  26. </view>
  27. <view class="form-item">
  28. <view class="form-label">群组描述</view>
  29. <uv-textarea
  30. v-model="groupForm.titleText"
  31. placeholder="请输入群组描述"
  32. :border="false"
  33. :maxlength="200"
  34. height="120"
  35. ></uv-textarea>
  36. </view>
  37. <view class="form-item">
  38. <view class="form-label">所属区域</view>
  39. <view class="category">
  40. <view class="tagList">
  41. <view
  42. :class="{act : t.id == groupForm.classId}"
  43. @click="clickCategory(t, i)"
  44. v-for="(t, i) in cityList"
  45. :key="i">
  46. {{ t.name }}
  47. </view>
  48. </view>
  49. </view>
  50. </view>
  51. <view class="form-item">
  52. <view class="form-label">群组公告</view>
  53. <uv-textarea
  54. v-model="groupForm.notice"
  55. placeholder="请输入群组公告(可选)"
  56. :border="false"
  57. :maxlength="500"
  58. height="120"
  59. ></uv-textarea>
  60. </view>
  61. <view class="form-item">
  62. <view class="form-label">预计人数</view>
  63. <uv-input
  64. v-model="groupForm.num"
  65. placeholder="请输入预计人数"
  66. type="number"
  67. :border="false"
  68. :clearable="true"
  69. ></uv-input>
  70. </view>
  71. <view class="form-item">
  72. <view class="form-label">分享信息</view>
  73. <uv-textarea
  74. v-model="groupForm.shareMsg"
  75. placeholder="请输入分享时显示的信息(可选)"
  76. :border="false"
  77. :maxlength="100"
  78. height="80"
  79. ></uv-textarea>
  80. </view>
  81. <!-- 群二维码上传 -->
  82. <view class="form-item">
  83. <view class="form-label">群二维码必填</view>
  84. <view class="qrcode-upload">
  85. <uv-upload
  86. :fileList="qrCodeFileList"
  87. :maxCount="1"
  88. width="200rpx"
  89. height="200rpx"
  90. name="qrCodeFileList"
  91. @delete="deleteQrCode"
  92. @afterRead="afterReadQrCode"
  93. :previewFullImage="true"
  94. :accept="'image'"
  95. :sizeType="['original', 'compressed']"
  96. :sourceType="['album', 'camera']">
  97. </uv-upload>
  98. <view class="qrcode-tip">请上传群聊二维码用户可通过此二维码加入群聊</view>
  99. </view>
  100. </view>
  101. </view>
  102. <!-- 创建按钮 -->
  103. <view class="submit-section">
  104. <uv-button
  105. type="primary"
  106. text="创建群组"
  107. :loading="submitting"
  108. @click="createGroup"
  109. ></uv-button>
  110. </view>
  111. </view>
  112. </view>
  113. </template>
  114. <script>
  115. import { mapState } from 'vuex'
  116. export default {
  117. data() {
  118. return {
  119. submitting: false,
  120. groupId: '', // 编辑时的群组ID
  121. groupForm: {
  122. title: '',
  123. titleText: '',
  124. image: '',
  125. classId: '',
  126. notice: '',
  127. num: '',
  128. qrCode: '',
  129. shareMsg: ''
  130. },
  131. qrCodeFileList: [] // 二维码文件列表
  132. }
  133. },
  134. computed: {
  135. ...mapState(['cityList'])
  136. },
  137. onLoad(options) {
  138. // 获取城市列表
  139. this.$store.commit('getCityList')
  140. // 如果有ID参数,说明是编辑模式
  141. if (options.id) {
  142. this.groupId = options.id
  143. this.getGroupDetail()
  144. }
  145. },
  146. methods: {
  147. // 获取群组详情(编辑模式)
  148. getGroupDetail() {
  149. this.$api('groupDetail', { id: this.groupId }, res => {
  150. if (res.code === 200 && res.result) {
  151. this.groupForm = {
  152. title: res.result.title || '',
  153. titleText: res.result.titleText || '',
  154. image: res.result.image || '',
  155. classId: res.result.classId || '',
  156. notice: res.result.notice || '',
  157. num: res.result.num || '',
  158. qrCode: res.result.qrCode || '',
  159. shareMsg: res.result.shareMsg || ''
  160. }
  161. // 如果有二维码,添加到文件列表
  162. if (res.result.qrCode) {
  163. this.qrCodeFileList = [{
  164. url: res.result.qrCode
  165. }]
  166. }
  167. } else {
  168. uni.showToast({
  169. title: res.message || '获取群组详情失败',
  170. icon: 'none'
  171. })
  172. }
  173. })
  174. },
  175. // 选择头像
  176. chooseAvatar() {
  177. uni.chooseImage({
  178. count: 1,
  179. sizeType: ['compressed'],
  180. sourceType: ['album', 'camera'],
  181. success: (res) => {
  182. this.uploadAvatar(res.tempFilePaths[0])
  183. }
  184. })
  185. },
  186. // 上传头像
  187. uploadAvatar(filePath) {
  188. if (this.$Oss && this.$Oss.ossUpload) {
  189. this.$Oss.ossUpload(filePath).then(url => {
  190. this.groupForm.image = url
  191. }).catch(err => {
  192. console.error('头像上传失败:', err)
  193. uni.showToast({
  194. title: '头像上传失败',
  195. icon: 'none'
  196. })
  197. })
  198. } else {
  199. // 如果没有OSS上传,直接使用本地路径
  200. this.groupForm.image = filePath
  201. }
  202. },
  203. // 区域选择
  204. clickCategory(item, index) {
  205. this.groupForm.classId = item.id
  206. },
  207. // 删除二维码
  208. deleteQrCode(e) {
  209. this.qrCodeFileList = []
  210. this.groupForm.qrCode = ''
  211. },
  212. // 二维码上传完成
  213. afterReadQrCode(e) {
  214. const file = e.file
  215. if (this.$Oss && this.$Oss.ossUpload) {
  216. this.$Oss.ossUpload(file.url).then(url => {
  217. this.qrCodeFileList = [{
  218. url: url
  219. }]
  220. this.groupForm.qrCode = url
  221. }).catch(err => {
  222. console.error('二维码上传失败:', err)
  223. uni.showToast({
  224. title: '二维码上传失败',
  225. icon: 'none'
  226. })
  227. })
  228. } else {
  229. // 如果没有OSS上传,直接使用本地路径
  230. this.qrCodeFileList = [{
  231. url: file.url
  232. }]
  233. this.groupForm.qrCode = file.url
  234. }
  235. },
  236. // 创建群组
  237. createGroup() {
  238. // 表单验证
  239. if (!this.groupForm.title.trim()) {
  240. uni.showToast({
  241. title: '请输入群组名称',
  242. icon: 'none'
  243. })
  244. return
  245. }
  246. if (!this.groupForm.titleText.trim()) {
  247. uni.showToast({
  248. title: '请输入群组描述',
  249. icon: 'none'
  250. })
  251. return
  252. }
  253. if (!this.groupForm.classId) {
  254. uni.showToast({
  255. title: '请选择所属区域',
  256. icon: 'none'
  257. })
  258. return
  259. }
  260. if (!this.groupForm.qrCode) {
  261. uni.showToast({
  262. title: '请上传群二维码',
  263. icon: 'none'
  264. })
  265. return
  266. }
  267. if (!this.groupForm.num || this.groupForm.num <= 0) {
  268. uni.showToast({
  269. title: '请输入有效的预计人数',
  270. icon: 'none'
  271. })
  272. return
  273. }
  274. this.submitting = true
  275. const apiMethod = this.groupId ? 'groupSaveOrUpdate' : 'groupSaveOrUpdate'
  276. const params = this.groupId ? { ...this.groupForm, id: this.groupId } : this.groupForm
  277. this.$api(apiMethod, params, res => {
  278. this.submitting = false
  279. if (res.code === 200) {
  280. uni.showToast({
  281. title: this.groupId ? '修改成功' : '创建成功',
  282. icon: 'success'
  283. })
  284. // 跳转到群组详情页
  285. setTimeout(() => {
  286. const groupId = this.groupId || res.result?.id || 'new'
  287. this.$utils.navigateTo('/pages_order/group/groupDetail?id=' + groupId)
  288. }, 1500)
  289. } else {
  290. uni.showToast({
  291. title: res.message || (this.groupId ? '修改失败' : '创建失败'),
  292. icon: 'none'
  293. })
  294. }
  295. })
  296. }
  297. }
  298. }
  299. </script>
  300. <style scoped lang="scss">
  301. .page {
  302. background-color: #f5f5f5;
  303. min-height: 100vh;
  304. .form-container {
  305. padding: 20rpx;
  306. .avatar-section {
  307. background-color: #fff;
  308. padding: 30rpx;
  309. border-radius: 20rpx;
  310. margin-bottom: 20rpx;
  311. .avatar-title {
  312. font-size: 30rpx;
  313. font-weight: bold;
  314. color: #333;
  315. margin-bottom: 20rpx;
  316. }
  317. .avatar-upload {
  318. display: flex;
  319. justify-content: center;
  320. .avatar-preview {
  321. width: 120rpx;
  322. height: 120rpx;
  323. border-radius: 20rpx;
  324. }
  325. .avatar-placeholder {
  326. width: 120rpx;
  327. height: 120rpx;
  328. border: 2rpx dashed #ddd;
  329. border-radius: 20rpx;
  330. display: flex;
  331. flex-direction: column;
  332. align-items: center;
  333. justify-content: center;
  334. text {
  335. font-size: 20rpx;
  336. color: #999;
  337. margin-top: 10rpx;
  338. }
  339. }
  340. }
  341. }
  342. .form-section {
  343. background-color: #fff;
  344. padding: 30rpx;
  345. border-radius: 20rpx;
  346. margin-bottom: 20rpx;
  347. .form-item {
  348. margin-bottom: 30rpx;
  349. &:last-child {
  350. margin-bottom: 0;
  351. }
  352. .form-label {
  353. font-size: 28rpx;
  354. color: #333;
  355. margin-bottom: 15rpx;
  356. font-weight: bold;
  357. }
  358. .picker-trigger {
  359. display: flex;
  360. justify-content: space-between;
  361. align-items: center;
  362. padding: 20rpx 0;
  363. border-bottom: 1rpx solid #f0f0f0;
  364. text {
  365. font-size: 28rpx;
  366. color: #333;
  367. }
  368. }
  369. .radio-item {
  370. margin-bottom: 15rpx;
  371. &:last-child {
  372. margin-bottom: 0;
  373. }
  374. }
  375. // 区域选择样式
  376. .category {
  377. .tagList {
  378. display: flex;
  379. flex-wrap: wrap;
  380. padding: 10rpx 0;
  381. view {
  382. background: rgba(91, 170, 255, 0.1);
  383. padding: 10rpx 20rpx;
  384. margin: 10rpx;
  385. border-radius: 10rpx;
  386. font-size: 26rpx;
  387. color: #5baaff;
  388. &.act {
  389. color: #fff;
  390. background: #5baaff;
  391. }
  392. }
  393. }
  394. }
  395. // 二维码上传样式
  396. .qrcode-upload {
  397. .qrcode-tip {
  398. font-size: 24rpx;
  399. color: #999;
  400. margin-top: 15rpx;
  401. line-height: 1.4;
  402. }
  403. }
  404. }
  405. }
  406. .submit-section {
  407. padding: 40rpx 0;
  408. .uv-button {
  409. width: 100%;
  410. height: 80rpx;
  411. border-radius: 40rpx;
  412. font-size: 32rpx;
  413. }
  414. }
  415. }
  416. }
  417. </style>