瑶都万能墙
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.

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