Merge branch 'wyfMain-dev'
Some checks failed
Check / lint (push) Has been cancelled
Check / typecheck (push) Has been cancelled
Check / build (build, 18.x, ubuntu-latest) (push) Has been cancelled
Check / build (build, 18.x, windows-latest) (push) Has been cancelled
Check / build (build:app, 18.x, ubuntu-latest) (push) Has been cancelled
Check / build (build:app, 18.x, windows-latest) (push) Has been cancelled
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Has been cancelled
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Has been cancelled
@ -39,7 +39,7 @@
|
||||
"quill-mention": "^6.0.2",
|
||||
"vconsole": "^3.15.1",
|
||||
"vue": "^3.3.8",
|
||||
"vue-i18n": "^9.6.5"
|
||||
"vue-i18n": "11.0.0-rc.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcloudio/types": "^3.4.7",
|
||||
|
@ -93,8 +93,8 @@ importers:
|
||||
specifier: ^3.3.8
|
||||
version: 3.4.35(typescript@5.5.4)
|
||||
vue-i18n:
|
||||
specifier: ^9.6.5
|
||||
version: 9.13.1(vue@3.4.35(typescript@5.5.4))
|
||||
specifier: 11.0.0-rc.1
|
||||
version: 11.0.0-rc.1(vue@3.4.35(typescript@5.5.4))
|
||||
devDependencies:
|
||||
'@dcloudio/types':
|
||||
specifier: ^3.4.7
|
||||
@ -1391,26 +1391,26 @@ packages:
|
||||
'@iconify/utils@2.1.32':
|
||||
resolution: {integrity: sha512-LeifFZPPKu28O3AEDpYJNdEbvS4/ojAPyIW+pF/vUpJTYnbTiXUHkCh0bwgFRzKvdpb8H4Fbfd/742++MF4fPQ==}
|
||||
|
||||
'@intlify/core-base@11.0.0-rc.1':
|
||||
resolution: {integrity: sha512-fnfZoa9pb1dKM3L1UkDUGLLrPFQ2BK98x4/fMqwS/fktUor34vQR/itPtfv652ZTplenXXLCEYjUYTGfDZgMTQ==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/core-base@9.1.9':
|
||||
resolution: {integrity: sha512-x5T0p/Ja0S8hs5xs+ImKyYckVkL4CzcEXykVYYV6rcbXxJTe2o58IquSqX9bdncVKbRZP7GlBU1EcRaQEEJ+vw==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@intlify/core-base@9.13.1':
|
||||
resolution: {integrity: sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/devtools-if@9.1.9':
|
||||
resolution: {integrity: sha512-oKSMKjttG3Ut/1UGEZjSdghuP3fwA15zpDPcjkf/1FjlOIm6uIBGMNS5jXzsZy593u+P/YcnrZD6cD3IVFz9vQ==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@intlify/message-compiler@11.0.0-rc.1':
|
||||
resolution: {integrity: sha512-TGw2uBfuTFTegZf/BHtUQBEKxl7Q/dVGLoqRIdw8lFsp9g/53sYn5iD+0HxIzdYjbWL6BTJMXCPUHp9PxDTRPw==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/message-compiler@9.1.9':
|
||||
resolution: {integrity: sha512-6YgCMF46Xd0IH2hMRLCssZI3gFG4aywidoWQ3QP4RGYQXQYYfFC54DxhSgfIPpVoPLQ+4AD29eoYmhiHZ+qLFQ==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@intlify/message-compiler@9.13.1':
|
||||
resolution: {integrity: sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/message-resolver@9.1.9':
|
||||
resolution: {integrity: sha512-Lx/DBpigeK0sz2BBbzv5mu9/dAlt98HxwbG7xLawC3O2xMF9MNWU5FtOziwYG6TDIjNq0O/3ZbOJAxwITIWXEA==}
|
||||
engines: {node: '>= 10'}
|
||||
@ -1419,14 +1419,14 @@ packages:
|
||||
resolution: {integrity: sha512-XgPw8+UlHCiie3fI41HPVa/VDJb3/aSH7bLhY1hJvlvNV713PFtb4p4Jo+rlE0gAoMsMCGcsiT982fImolSltg==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@intlify/shared@11.0.0-rc.1':
|
||||
resolution: {integrity: sha512-8tR1xe7ZEbkabTuE/tNhzpolygUn9OaYp9yuYAF4MgDNZg06C3Qny80bes2/e9/Wm3aVkPUlCw6WgU7mQd0yEg==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/shared@9.1.9':
|
||||
resolution: {integrity: sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
'@intlify/shared@9.13.1':
|
||||
resolution: {integrity: sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==}
|
||||
engines: {node: '>= 16'}
|
||||
|
||||
'@intlify/vue-devtools@9.1.9':
|
||||
resolution: {integrity: sha512-YPehH9uL4vZcGXky4Ev5qQIITnHKIvsD2GKGXgqf+05osMUI6WSEQHaN9USRa318Rs8RyyPCiDfmA0hRu3k7og==}
|
||||
engines: {node: '>= 10'}
|
||||
@ -4819,8 +4819,8 @@ packages:
|
||||
'@vue/composition-api':
|
||||
optional: true
|
||||
|
||||
vue-i18n@9.13.1:
|
||||
resolution: {integrity: sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==}
|
||||
vue-i18n@11.0.0-rc.1:
|
||||
resolution: {integrity: sha512-qbdCbA537HEdr2yXQ4ec/OMDsoHjod1DwnWbrf+l4Cu/O7CYTCKsOyITUm3RmrCJgRnoVycuR6i/JWdNTJvD5g==}
|
||||
engines: {node: '>= 16'}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
@ -6730,6 +6730,11 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@intlify/core-base@11.0.0-rc.1':
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 11.0.0-rc.1
|
||||
'@intlify/shared': 11.0.0-rc.1
|
||||
|
||||
'@intlify/core-base@9.1.9':
|
||||
dependencies:
|
||||
'@intlify/devtools-if': 9.1.9
|
||||
@ -6739,26 +6744,21 @@ snapshots:
|
||||
'@intlify/shared': 9.1.9
|
||||
'@intlify/vue-devtools': 9.1.9
|
||||
|
||||
'@intlify/core-base@9.13.1':
|
||||
dependencies:
|
||||
'@intlify/message-compiler': 9.13.1
|
||||
'@intlify/shared': 9.13.1
|
||||
|
||||
'@intlify/devtools-if@9.1.9':
|
||||
dependencies:
|
||||
'@intlify/shared': 9.1.9
|
||||
|
||||
'@intlify/message-compiler@11.0.0-rc.1':
|
||||
dependencies:
|
||||
'@intlify/shared': 11.0.0-rc.1
|
||||
source-map-js: 1.2.0
|
||||
|
||||
'@intlify/message-compiler@9.1.9':
|
||||
dependencies:
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
source-map: 0.6.1
|
||||
|
||||
'@intlify/message-compiler@9.13.1':
|
||||
dependencies:
|
||||
'@intlify/shared': 9.13.1
|
||||
source-map-js: 1.2.0
|
||||
|
||||
'@intlify/message-resolver@9.1.9': {}
|
||||
|
||||
'@intlify/runtime@9.1.9':
|
||||
@ -6767,9 +6767,9 @@ snapshots:
|
||||
'@intlify/message-resolver': 9.1.9
|
||||
'@intlify/shared': 9.1.9
|
||||
|
||||
'@intlify/shared@9.1.9': {}
|
||||
'@intlify/shared@11.0.0-rc.1': {}
|
||||
|
||||
'@intlify/shared@9.13.1': {}
|
||||
'@intlify/shared@9.1.9': {}
|
||||
|
||||
'@intlify/vue-devtools@9.1.9':
|
||||
dependencies:
|
||||
@ -10890,10 +10890,10 @@ snapshots:
|
||||
dependencies:
|
||||
vue: 3.4.35(typescript@5.5.4)
|
||||
|
||||
vue-i18n@9.13.1(vue@3.4.35(typescript@5.5.4)):
|
||||
vue-i18n@11.0.0-rc.1(vue@3.4.35(typescript@5.5.4)):
|
||||
dependencies:
|
||||
'@intlify/core-base': 9.13.1
|
||||
'@intlify/shared': 9.13.1
|
||||
'@intlify/core-base': 11.0.0-rc.1
|
||||
'@intlify/shared': 11.0.0-rc.1
|
||||
'@vue/devtools-api': 6.6.3
|
||||
vue: 3.4.35(typescript@5.5.4)
|
||||
|
||||
|
@ -18,6 +18,7 @@ init()
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "@/static/css/color.scss";
|
||||
@import "@/static/css/font.scss";
|
||||
/* #ifdef APP-NVUE */
|
||||
@import '@/uni_modules/tmui/scss/nvue.css';
|
||||
/* #endif */
|
||||
|
@ -207,6 +207,7 @@ export const ServeGroupAssignAdmin = (data) => {
|
||||
})
|
||||
}
|
||||
|
||||
//指定人员禁言
|
||||
export const ServeGroupNoSpeak = (data) => {
|
||||
return request({
|
||||
url: '/api/v1/group/no-speak',
|
||||
@ -214,4 +215,3 @@ export const ServeGroupNoSpeak = (data) => {
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
|
47
src/api/search/index.js
Normal file
@ -0,0 +1,47 @@
|
||||
import request from '@/service/index.js'
|
||||
import qs from 'qs'
|
||||
|
||||
// ES搜索聊天记录-主页搜索什么都有
|
||||
export const ServeSeachQueryAll = (data) => {
|
||||
return request({
|
||||
url: '/api/v1/elasticsearch/query-all',
|
||||
method: 'POST',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
// ES搜索用户数据
|
||||
export const ServeQueryUser = (data) => {
|
||||
return request({
|
||||
url: '/api/v1/elasticsearch/query-user',
|
||||
method: 'POST',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
// ES搜索群组数据
|
||||
export const ServeQueryGroup = (data) => {
|
||||
return request({
|
||||
url: '/api/v1/elasticsearch/query-group',
|
||||
method: 'POST',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
// ES搜索聊天记录-指定用户、指定群、群与用户概览
|
||||
export const ServeTalkRecord = (data) => {
|
||||
return request({
|
||||
url: '/api/v1/elasticsearch/query-talk-record',
|
||||
method: 'POST',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
//查看存在聊天记录的天数
|
||||
export const ServeTalkDate = (data) => {
|
||||
return request({
|
||||
url: '/api/v1/talk/date',
|
||||
method: 'POST',
|
||||
data,
|
||||
})
|
||||
}
|
42
src/components/custom-btn/custom-btn.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div class="custom-btn" :class="props.isBottom ? 'custom-btn-bottom' : ''">
|
||||
<wd-button custom-class="custom-btn-class" @click="clickBtn">{{ props.btnText }}</wd-button>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive } from 'vue'
|
||||
import { defineProps, defineEmits } from 'vue'
|
||||
const state = reactive({})
|
||||
const emits = defineEmits(['clickBtn'])
|
||||
const props = defineProps({
|
||||
isBottom: false, //是否底部按钮
|
||||
btnText: '', //按钮文字
|
||||
})
|
||||
|
||||
//点击
|
||||
const clickBtn = () => {
|
||||
emits('clickBtn')
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.custom-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.custom-btn-class {
|
||||
background-color: $theme-primary;
|
||||
padding: 18rpx 185rpx;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
.custom-btn-bottom {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 14rpx 0 72rpx;
|
||||
}
|
||||
</style>
|
58
src/components/custom-input/custom-input.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="custom-search-input">
|
||||
<tm-input
|
||||
class="search-input"
|
||||
placeholder="请输入…"
|
||||
color="#F9F9FD"
|
||||
:round="1"
|
||||
prefix="tmicon-search"
|
||||
prefixColor="#46299D"
|
||||
:prefixLabel="props?.first_talk_record_infos?.receiver_name"
|
||||
v-model.lazy="state.searchText"
|
||||
@input="inputSearchText"
|
||||
:showClear="true"
|
||||
@clear="clearInput"
|
||||
></tm-input>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, reactive, watch } from 'vue'
|
||||
const props = defineProps({
|
||||
searchText: String,
|
||||
first_talk_record_infos: Object,
|
||||
})
|
||||
const state = reactive({
|
||||
searchText: '', //搜索内容
|
||||
})
|
||||
const emits = defineEmits(['inputSearchText'])
|
||||
|
||||
watch(
|
||||
() => props.searchText,
|
||||
(newSearchText) => {
|
||||
state.searchText = newSearchText
|
||||
},
|
||||
)
|
||||
|
||||
//清除输入的搜索内容
|
||||
const clearInput = () => {
|
||||
inputSearchText('')
|
||||
}
|
||||
|
||||
//输入搜索文本
|
||||
const inputSearchText = (e) => {
|
||||
emits('inputSearchText', e)
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.custom-search-input {
|
||||
width: 100%;
|
||||
.search-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-input::v-deep .tmicon-times-circle-fill::before {
|
||||
content: '\e82a';
|
||||
color: #d2d2d5;
|
||||
}
|
||||
}
|
||||
</style>
|
117
src/pages.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"easycom":{
|
||||
"easycom": {
|
||||
"autoscan": true,
|
||||
"custom":{
|
||||
"custom": {
|
||||
"^tm-(.*)": "@/tmui/components/tm-$1/tm-$1.vue"
|
||||
}
|
||||
},
|
||||
@ -11,7 +11,7 @@
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh":false
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -19,7 +19,7 @@
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh":false
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -27,7 +27,7 @@
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh":false
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -35,7 +35,7 @@
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh":false
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -59,7 +59,7 @@
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh":false
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -67,23 +67,116 @@
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh":false
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/index",
|
||||
"type": "page",
|
||||
"style": {}
|
||||
},
|
||||
{
|
||||
"path": "pages/search/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/search/moreResult/moreResult",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/search/moreResult/moreResultDetail",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/search/searchByCondition/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chatSettings/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chatSettings/groupManage/manageNotice",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chatSettings/groupManage/editGroupName",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chatSettings/groupManage/editAvatar",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chatSettings/groupManage/manageGroupMembers",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chatSettings/groupManage/manageGroupSilence",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chatSettings/groupManage/selectMembers",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chatSettings/groupManage/manageGroupAdmin",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
"globalStyle": {
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"navigationBarBackgroundColor": "#FFFFFF",
|
||||
"navigationBarTextstyle": "black",
|
||||
"navigationBarTitleText":""
|
||||
|
||||
"navigationBarTitleText": ""
|
||||
},
|
||||
"subPackages": []
|
||||
}
|
||||
|
117
src/pages/chatSettings/components/groupMembersList.vue
Normal file
@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div class="group-member-list">
|
||||
<div
|
||||
class="group-member-list-each"
|
||||
v-for="(memberItem, memberIndex) in props?.memberList"
|
||||
>
|
||||
<div
|
||||
class="group-member-each"
|
||||
v-if="
|
||||
props.memberListsLimit ? memberIndex < props.memberListsLimit : true
|
||||
"
|
||||
>
|
||||
<div class="group-member-avatar">
|
||||
<img v-if="memberItem.avatar" :src="memberItem.avatar" />
|
||||
<span v-if="!memberItem.avatar" class="text-[24rpx] font-bold">
|
||||
{{
|
||||
memberItem.nickname.length >= 2
|
||||
? memberItem.nickname.slice(-2)
|
||||
: memberItem.nickname
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="group-member-tag" v-if="memberIndex < 3">
|
||||
<span class="text-[16rpx] font-regular">
|
||||
{{ $t('group.identify.admin') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="group-member-name">
|
||||
<span class="text-[24rpx] font-regular">
|
||||
{{ memberItem.nickname }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { defineProps } from 'vue'
|
||||
const props = defineProps({
|
||||
memberList: Array, //人员列表
|
||||
memberListsLimit: Number, //人员列表数量限制
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.group-member-list {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
.group-member-list-each {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: calc(100% / 5);
|
||||
.group-member-each {
|
||||
padding: 32rpx 0 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
.group-member-avatar {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(to right, #674bbc, #46299d);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
span {
|
||||
line-height: 34rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.group-member-tag {
|
||||
position: absolute;
|
||||
bottom: 34rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #cf3050;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 12rpx;
|
||||
span {
|
||||
line-height: 22rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.group-member-name {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8rpx 0 0;
|
||||
width: 100%;
|
||||
span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 34rpx;
|
||||
color: #919191;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
142
src/pages/chatSettings/components/select-member-item.vue
Normal file
@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div
|
||||
class="select-member-item"
|
||||
@click="clickItem(props?.memberItem)"
|
||||
:class="
|
||||
props.itemStyle === 'card'
|
||||
? 'select-member-item-card'
|
||||
: 'select-member-item-list'
|
||||
"
|
||||
>
|
||||
<div class="member-info">
|
||||
<slot name="left"></slot>
|
||||
<div
|
||||
class="select-member-item-avatar"
|
||||
v-if="
|
||||
props?.manageType === 'silence' ||
|
||||
props?.manageType === 'searchRecord'
|
||||
"
|
||||
>
|
||||
<img v-if="avatarImg !== 'textImg'" :src="avatarImg" />
|
||||
<span v-if="avatarImg === 'textImg'" class="text-[24rpx] font-bold">
|
||||
{{ imgText }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="select-member-item-name"
|
||||
v-if="
|
||||
props?.manageType === 'silence' ||
|
||||
props?.manageType === 'searchRecord'
|
||||
"
|
||||
>
|
||||
<span class="text-[28rpx] font-medium">{{ nameText }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="operate-btns">
|
||||
<div class="btn-undo-silence">
|
||||
<span v-if="props?.memberItem?.is_mute === 1">
|
||||
{{ $t('chatSettings.btn.undoSilence') }}
|
||||
</span>
|
||||
<span v-if="props?.memberItem?.is_mute === 1">
|
||||
{{ $t('silence.tag.hasDone') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed, defineProps, defineEmits } from 'vue'
|
||||
import { onMounted, reactive } from 'vue'
|
||||
|
||||
const emits = defineEmits(['clickItem'])
|
||||
|
||||
const props = defineProps({
|
||||
memberItem: Object, //人员
|
||||
manageType: String, //管理类型
|
||||
itemStyle: String,
|
||||
})
|
||||
onMounted(() => {})
|
||||
|
||||
//头像
|
||||
const avatarImg = computed(() => {
|
||||
let avatar_img = props?.memberItem?.avatar
|
||||
if (!avatar_img) {
|
||||
avatar_img = 'textImg'
|
||||
}
|
||||
return avatar_img
|
||||
})
|
||||
|
||||
//名字
|
||||
const nameText = computed(() => {
|
||||
let name = props?.memberItem?.nickname
|
||||
return name
|
||||
})
|
||||
|
||||
//文字头像
|
||||
const imgText = computed(() => {
|
||||
return nameText.value.length >= 2 ? nameText.value.slice(-2) : nameText.value
|
||||
})
|
||||
|
||||
//点击item
|
||||
const clickItem = () => {
|
||||
emits('clickItem')
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.select-member-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 18rpx 34rpx;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
.member-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
.select-member-item-avatar {
|
||||
background: linear-gradient(to right, #674bbc, #46299d);
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 20rpx 0 0;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
span {
|
||||
color: #fff;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
}
|
||||
.select-member-item-name {
|
||||
span {
|
||||
color: $theme-text;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.operate-btns {
|
||||
.btn-undo-silence {
|
||||
span {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-member-item-card {
|
||||
margin: 20rpx 0 0;
|
||||
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
.select-member-item-list {
|
||||
border-bottom: 1px solid $theme-border-color;
|
||||
}
|
||||
</style>
|
118
src/pages/chatSettings/components/settingFormItem.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="setting-form-item">
|
||||
<div class="item-main">
|
||||
<div class="item-main-label">
|
||||
<span class="text-[32rpx] font-regular">{{ props?.item?.label }}</span>
|
||||
</div>
|
||||
<div class="item-main-value" @click="toManagePage(props?.item)">
|
||||
<span class="text-[32rpx] font-regular" v-if="props?.item?.value">
|
||||
{{ props?.item?.value }}
|
||||
</span>
|
||||
<img
|
||||
v-if="props?.item?.hasPointer"
|
||||
src="/src/static/image/chatSettings/pointer.png"
|
||||
/>
|
||||
<tm-switch
|
||||
:width="88"
|
||||
:height="48"
|
||||
v-if="props?.item?.customInfo && props?.item?.customInfo === 'switch'"
|
||||
barIcon=""
|
||||
color="#46299D"
|
||||
unCheckedColor="#EEEEEE"
|
||||
:modelValue="modelValue"
|
||||
@change="changeSwitch($event, props?.item)"
|
||||
></tm-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-sub" v-if="props?.item?.subValue">
|
||||
<span class="text-[32rpx] font-regular">{{ props?.item?.subValue }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, computed } from 'vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
sessionInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
})
|
||||
const emits = defineEmits(['toManagePage', 'changeSwitch'])
|
||||
const toManagePage = (item) => {
|
||||
emits('toManagePage', item.label)
|
||||
}
|
||||
const modelValue = computed(() => {
|
||||
let switchStatus = false
|
||||
if (
|
||||
props?.item?.label === t('chat.settings.topSession') &&
|
||||
props?.sessionInfo?.is_top == 1
|
||||
) {
|
||||
switchStatus = true
|
||||
}
|
||||
if (
|
||||
props?.item?.label === t('chat.settings.messageNoDisturb') &&
|
||||
props?.sessionInfo?.is_disturb == 1
|
||||
) {
|
||||
switchStatus = true
|
||||
}
|
||||
return switchStatus
|
||||
})
|
||||
|
||||
//切换开关选择
|
||||
const changeSwitch = (e, item) => {
|
||||
emits('changeSwitch', e, item.label)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.setting-form-item {
|
||||
.item-main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.item-main-label {
|
||||
flex-shrink: 0;
|
||||
span {
|
||||
line-height: 44rpx;
|
||||
color: $theme-text;
|
||||
}
|
||||
}
|
||||
.item-main-value {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
span {
|
||||
line-height: 44rpx;
|
||||
color: #747474;
|
||||
}
|
||||
img {
|
||||
width: 11rpx;
|
||||
height: 18rpx;
|
||||
margin: 0 0 0 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-sub {
|
||||
margin: 28rpx 0 0;
|
||||
span {
|
||||
line-height: 44rpx;
|
||||
color: #747474;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
95
src/pages/chatSettings/groupManage/editAvatar.vue
Normal file
@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div class="outer-layer manage-group-info-page">
|
||||
<div class="root">
|
||||
<ZPaging ref="zPaging" :show-scrollbar="false">
|
||||
<template #top>
|
||||
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span class="text-[34rpx] font-medium">
|
||||
{{ $t('chat.settings.editAvatar') }}
|
||||
</span>
|
||||
</div>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div class="edit-group-info">
|
||||
<div class="group-avatar">
|
||||
<img :src="state.groupAvatar" />
|
||||
</div>
|
||||
</div>
|
||||
<customBtn :btnText="$t('button.text.edit')"></customBtn>
|
||||
<template #bottom>
|
||||
<div class="app-logo-icon">
|
||||
<img src="/src/static/image/chatSettings/app-icon.png" />
|
||||
</div>
|
||||
</template>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import customBtn from '@/components/custom-btn/custom-btn.vue'
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const state = reactive({
|
||||
pageTitle: '', //页面标题
|
||||
groupAvatar: '', //群头像
|
||||
groupName: '', //群名称
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
if (options.groupAvatar) {
|
||||
state.groupAvatar = options.groupAvatar
|
||||
}
|
||||
})
|
||||
|
||||
//点击清空群名称输入
|
||||
const clearGroupNameInput = () => {
|
||||
state.groupName = ''
|
||||
}
|
||||
|
||||
//点击确认修改
|
||||
const confirmEdit = () => {
|
||||
console.log(state.groupName)
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.outer-layer {
|
||||
flex: 1;
|
||||
background-image: url('@/static/image/clockIn/z3280@3x.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.edit-group-info {
|
||||
margin: 158rpx 94rpx 100rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 6px 12px 2px rgba(0, 0, 0, 0.16);
|
||||
padding: 50rpx;
|
||||
border-radius: 16rpx;
|
||||
.group-avatar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
width: 460rpx;
|
||||
height: 460rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-logo-icon {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 0 44rpx;
|
||||
img {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
127
src/pages/chatSettings/groupManage/editGroupName.vue
Normal file
@ -0,0 +1,127 @@
|
||||
<template>
|
||||
<div class="outer-layer manage-group-info-page">
|
||||
<div class="root">
|
||||
<ZPaging ref="zPaging" :show-scrollbar="false">
|
||||
<template #top>
|
||||
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span class="text-[34rpx] font-medium">
|
||||
{{ $t('chat.settings.editGroupName') }}
|
||||
</span>
|
||||
</div>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div class="edit-group-info">
|
||||
<div class="group-avatar">
|
||||
<img :src="state.groupAvatar" />
|
||||
</div>
|
||||
<div class="group-name">
|
||||
<span class="text-[28rpx] font-medium">
|
||||
{{ $t('chat.settings.groupName') }}
|
||||
</span>
|
||||
<div class="groupNameInputArea">
|
||||
<input
|
||||
class="groupNameInput"
|
||||
:placeholder="$t('edit.groupName.placeholder')"
|
||||
placeholder-style="color:#B4B4B4;font-size:28rpx;font-weight:500;line-height:40rpx;"
|
||||
v-model="state.groupName"
|
||||
/>
|
||||
<img
|
||||
class="groupName-input-clearBtn"
|
||||
src="/src/static/image/chatSettings/clear-btn.png"
|
||||
@click="clearGroupNameInput"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #bottom>
|
||||
<customBtn
|
||||
:isBottom="true"
|
||||
:btnText="$t('ok')"
|
||||
@clickBtn="confirmEdit"
|
||||
></customBtn>
|
||||
</template>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import customBtn from '@/components/custom-btn/custom-btn.vue'
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const state = reactive({
|
||||
pageTitle: '', //页面标题
|
||||
groupAvatar: '', //群头像
|
||||
groupName: '', //群名称
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
if (options.groupAvatar) {
|
||||
state.groupAvatar = options.groupAvatar
|
||||
}
|
||||
})
|
||||
|
||||
//点击清空群名称输入
|
||||
const clearGroupNameInput = () => {
|
||||
state.groupName = ''
|
||||
}
|
||||
|
||||
//点击确认修改
|
||||
const confirmEdit = () => {
|
||||
console.log(state.groupName)
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.outer-layer {
|
||||
flex: 1;
|
||||
background-image: url('@/static/image/clockIn/z3280@3x.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.edit-group-info {
|
||||
.group-avatar {
|
||||
padding: 250rpx 0 88rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
width: 192rpx;
|
||||
height: 192rpx;
|
||||
}
|
||||
}
|
||||
.group-name {
|
||||
padding: 0 32rpx;
|
||||
span {
|
||||
display: inline-block;
|
||||
padding: 0 32rpx 10rpx;
|
||||
color: $theme-text;
|
||||
}
|
||||
.groupNameInputArea {
|
||||
position: relative;
|
||||
.groupNameInput {
|
||||
background-color: #fff;
|
||||
height: 110rpx;
|
||||
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
|
||||
padding: 0 74rpx 0 32rpx;
|
||||
color: #B747474;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
.groupName-input-clearBtn {
|
||||
position: absolute;
|
||||
right: 22rpx;
|
||||
top: 40rpx;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
106
src/pages/chatSettings/groupManage/manageGroupAdmin.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="outer-layer manage-group-silence-page">
|
||||
<div class="root">
|
||||
<ZPaging ref="zPaging" :show-scrollbar="false">
|
||||
<template #top>
|
||||
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span class="text-[34rpx] font-medium">
|
||||
{{ $t('chat.settings.groupAdmin') }}
|
||||
</span>
|
||||
</div>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div class="manage-group-silence">
|
||||
<span class="manage-group-silence-title text-[28rpx] font-regular">
|
||||
{{ $t('chat.settings.groupAdmin') }}
|
||||
</span>
|
||||
<div
|
||||
class="add-silence-member-btn chat-settings-card"
|
||||
@click="toSelectMembersPage"
|
||||
>
|
||||
<img src="/src/static/image/chatSettings/add-btn.png" />
|
||||
<span class="text-[28rpx] font-medium">
|
||||
{{ $t('chat.manage.addAdmin') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { computed, onMounted, reactive } from 'vue'
|
||||
|
||||
import { useGroupStore, useDialogueStore } from '@/store'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
const groupStore = useGroupStore()
|
||||
const dialogueStore = useDialogueStore()
|
||||
|
||||
const dialogueParams = reactive({
|
||||
adminList: computed(() => dialogueStore.getAdminList),
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
silenceAllBtn: null, //全员禁言按钮
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
console.log(dialogueParams.adminList)
|
||||
})
|
||||
|
||||
//点击跳转到添加禁言成员页面
|
||||
const toSelectMembersPage = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/chatSettings/groupManage/selectMembers?manageType=admin',
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.outer-layer {
|
||||
flex: 1;
|
||||
background-image: url('@/static/image/clockIn/z3280@3x.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.manage-group-silence {
|
||||
padding: 20rpx 32rpx;
|
||||
.manage-group-silence-title {
|
||||
line-height: 40rpx;
|
||||
color: #959598;
|
||||
}
|
||||
.add-silence-member-btn {
|
||||
padding: 32rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin: 0 22rpx 0 0;
|
||||
}
|
||||
span {
|
||||
line-height: 40rpx;
|
||||
color: $theme-text;
|
||||
}
|
||||
}
|
||||
.chat-settings-card {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
margin: 20rpx 0 0;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
|
||||
}
|
||||
}
|
||||
</style>
|
58
src/pages/chatSettings/groupManage/manageGroupMembers.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="outer-layer manage-group-members-page">
|
||||
<div class="root">
|
||||
<ZPaging
|
||||
ref="zPaging"
|
||||
:show-scrollbar="false"
|
||||
:use-virtual-list="true"
|
||||
:virtual-list-col="5"
|
||||
:auto="false"
|
||||
:refresher-enabled="false"
|
||||
:loading-more-enabled="false"
|
||||
>
|
||||
<template #top>
|
||||
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span class="text-[34rpx] font-medium">
|
||||
{{ $t('chat.settings.groupMember') }}
|
||||
</span>
|
||||
</div>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div class="group-members-list">
|
||||
<groupMemberList
|
||||
:memberList="talkParams?.memberList"
|
||||
></groupMemberList>
|
||||
</div>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import groupMemberList from '../components/groupMembersList.vue'
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
||||
import { ref, computed, reactive } from 'vue'
|
||||
import { useDialogueStore } from '@/store'
|
||||
|
||||
const dialogueStore = useDialogueStore()
|
||||
const talkParams = reactive({
|
||||
memberList: computed(() => dialogueStore.members),
|
||||
})
|
||||
|
||||
const zPaging = ref()
|
||||
useZPaging(zPaging)
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.outer-layer {
|
||||
flex: 1;
|
||||
background-image: url('@/static/image/clockIn/z3280@3x.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.group-members-list {
|
||||
margin: 20rpx 32rpx;
|
||||
padding: 0 0 32rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
129
src/pages/chatSettings/groupManage/manageGroupSilence.vue
Normal file
@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div class="outer-layer manage-group-silence-page">
|
||||
<div class="root">
|
||||
<ZPaging ref="zPaging" :show-scrollbar="false">
|
||||
<template #top>
|
||||
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span class="text-[34rpx] font-medium">
|
||||
{{ $t('chat.settings.groupGag') }}
|
||||
</span>
|
||||
</div>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div class="manage-group-silence">
|
||||
<span class="manage-group-silence-title text-[28rpx] font-regular">
|
||||
{{ $t('chat.manage.silenceMember') }}
|
||||
</span>
|
||||
<div
|
||||
class="add-silence-member-btn chat-settings-card"
|
||||
@click="toSelectMembersPage"
|
||||
>
|
||||
<img src="/src/static/image/chatSettings/add-btn.png" />
|
||||
<span class="text-[28rpx] font-medium">
|
||||
{{ $t('chat.manage.addSilenceMember') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="silence-all-btn chat-settings-card">
|
||||
<settingFormItem
|
||||
:item="state.silenceAllBtn"
|
||||
:sessionInfo="state?.sessionInfo"
|
||||
@changeSwitch="changeSwitch"
|
||||
></settingFormItem>
|
||||
</div>
|
||||
</div>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import settingFormItem from '../components/settingFormItem.vue'
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { computed, onMounted, reactive } from 'vue'
|
||||
|
||||
import { useGroupStore, useDialogueStore } from '@/store'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
const groupStore = useGroupStore()
|
||||
const dialogueStore = useDialogueStore()
|
||||
|
||||
const dialogueParams = reactive({
|
||||
silenceMembersList: computed(() => dialogueStore.getAdminList),
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
silenceAllBtn: null, //全员禁言按钮
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
console.log(dialogueParams.silenceMembersList)
|
||||
state.silenceAllBtn = {
|
||||
label: t('chat.manage.silenceAll'),
|
||||
hasPointer: false,
|
||||
value: '',
|
||||
subValue: t('chat.manage.silenceAllHint'),
|
||||
customInfo: 'switch',
|
||||
}
|
||||
})
|
||||
|
||||
//切换开关选择
|
||||
const changeSwitch = (switchStatus, label) => {
|
||||
console.log(switchStatus, label)
|
||||
}
|
||||
|
||||
//点击跳转到添加禁言成员页面
|
||||
const toSelectMembersPage = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/chatSettings/groupManage/selectMembers?manageType=silence',
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.outer-layer {
|
||||
flex: 1;
|
||||
background-image: url('@/static/image/clockIn/z3280@3x.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.manage-group-silence {
|
||||
padding: 20rpx 32rpx;
|
||||
.manage-group-silence-title {
|
||||
line-height: 40rpx;
|
||||
color: #959598;
|
||||
}
|
||||
.add-silence-member-btn {
|
||||
padding: 32rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin: 0 22rpx 0 0;
|
||||
}
|
||||
span {
|
||||
line-height: 40rpx;
|
||||
color: $theme-text;
|
||||
}
|
||||
}
|
||||
.silence-all-btn {
|
||||
padding: 32rpx;
|
||||
}
|
||||
.chat-settings-card {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
margin: 20rpx 0 0;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
|
||||
}
|
||||
}
|
||||
</style>
|
141
src/pages/chatSettings/groupManage/manageNotice.vue
Normal file
@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div class="outer-layer manage-notice-page">
|
||||
<div class="root">
|
||||
<ZPaging ref="zPaging" :show-scrollbar="false">
|
||||
<template #top>
|
||||
<tm-navbar :hideBack="true" hideHome title="" :leftWidth="220">
|
||||
<template #left>
|
||||
<div class="nav-bar-cancel-btn">
|
||||
<span class="text-[34rpx] font-regular" @click="toPrevPage">
|
||||
{{ $t('cancel') }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span class="text-[34rpx] font-medium">
|
||||
{{ $t('chat.settings.groupNotice') }}
|
||||
</span>
|
||||
</div>
|
||||
<template #right>
|
||||
<div
|
||||
class="nav-bar-done-btn"
|
||||
:class="state.canDoComplete ? 'nav-bar-done-btn-can-do' : ''"
|
||||
>
|
||||
<span class="text-[34rpx] font-regular">
|
||||
{{ $t('button.text.done') }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div class="notice-text-area">
|
||||
<wd-textarea
|
||||
style="height: 100%;"
|
||||
v-model="state.groupNotice"
|
||||
:placeholder="$t('input.placeholder.enter')"
|
||||
:maxlength="500"
|
||||
:show-word-limit="true"
|
||||
@input="inputGroupNotice"
|
||||
/>
|
||||
</div>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const state = reactive({
|
||||
groupNotice: '', //群公告
|
||||
canDoComplete: false, //是否可以点击完成按钮
|
||||
})
|
||||
|
||||
//点击返回上一页
|
||||
const toPrevPage = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
})
|
||||
}
|
||||
|
||||
//输入群公告
|
||||
const inputGroupNotice = (e) => {
|
||||
state.groupNotice = e
|
||||
if (e.trim()) {
|
||||
state.canDoComplete = true
|
||||
} else {
|
||||
state.canDoComplete = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.outer-layer {
|
||||
flex: 1;
|
||||
background-image: url('@/static/image/clockIn/z3280@3x.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.manage-notice-page {
|
||||
::v-deep .zp-paging-container-content {
|
||||
height: 100%;
|
||||
}
|
||||
.nav-bar-cancel-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 0 0 42rpx;
|
||||
span {
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
.nav-bar-done-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 36rpx 0 0;
|
||||
padding: 6rpx 24rpx;
|
||||
background-color: #f3f3f3;
|
||||
border-radius: 8rpx;
|
||||
span {
|
||||
color: #bababa;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-bar-done-btn-can-do {
|
||||
background-color: $theme-primary;
|
||||
span {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-text-area {
|
||||
padding: 20rpx 32rpx;
|
||||
height: 100%;
|
||||
|
||||
::v-deep .wd-textarea {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
::v-deep .wd-textarea__value {
|
||||
padding-right: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
::v-deep .wd-textarea__inner {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
::v-deep .uni-textarea-compute {
|
||||
div {
|
||||
font-size: 32rpx;
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
401
src/pages/chatSettings/groupManage/selectMembers.vue
Normal file
@ -0,0 +1,401 @@
|
||||
<template>
|
||||
<div class="outer-layer select-members-page">
|
||||
<div class="root">
|
||||
<ZPaging
|
||||
ref="zPaging"
|
||||
:show-scrollbar="false"
|
||||
:use-virtual-list="true"
|
||||
:virtual-list-col="5"
|
||||
:refresher-enabled="false"
|
||||
:loading-more-enabled="false"
|
||||
@scroll="onScroll"
|
||||
>
|
||||
<template #top>
|
||||
<tm-navbar
|
||||
:hideBack="false"
|
||||
hideHome
|
||||
title=""
|
||||
:leftWidth="220"
|
||||
id="topArea"
|
||||
>
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span
|
||||
class="text-[34rpx] font-medium"
|
||||
v-if="state.manageType === 'silence'"
|
||||
>
|
||||
{{ $t('chat.manage.addSilenceMember') }}
|
||||
</span>
|
||||
<span
|
||||
class="text-[34rpx] font-medium"
|
||||
v-if="state.manageType === 'admin'"
|
||||
>
|
||||
{{ $t('chat.manage.addAdmin') }}
|
||||
</span>
|
||||
<span
|
||||
class="text-[34rpx] font-medium"
|
||||
v-if="state.manageType === 'searchRecord'"
|
||||
>
|
||||
{{ $t('search.condition.member') }}
|
||||
</span>
|
||||
</div>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div class="select-members">
|
||||
<div class="search-member">
|
||||
<customInput
|
||||
:searchText="state.searchText"
|
||||
@inputSearchText="inputSearchText"
|
||||
></customInput>
|
||||
</div>
|
||||
<div
|
||||
class="member-list"
|
||||
:style="{
|
||||
padding: state.manageType === 'searchRecord' ? '20rpx 0 0' : '',
|
||||
}"
|
||||
>
|
||||
<div class="member-list-alphabet-anchor-point">
|
||||
<div
|
||||
class="member-list-alphabet-anchor-point-each"
|
||||
v-for="(alphabetItem, alphabetIndex) in state?.alphabet"
|
||||
:key="alphabetIndex"
|
||||
:style="{
|
||||
margin: state?.alphabet?.length > 17 ? '0' : '',
|
||||
}"
|
||||
@click.stop="scrollToView(alphabetItem)"
|
||||
>
|
||||
<span
|
||||
class="text-[32rpx] font-regular"
|
||||
:style="{
|
||||
color:
|
||||
state.currentAlphabet === alphabetItem ? '#7A58DE' : '',
|
||||
}"
|
||||
>
|
||||
{{ alphabetItem }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="member-list-alphabet"
|
||||
v-for="(alphabetItem, alphabetIndex) in state.resultMemberList"
|
||||
:key="alphabetIndex"
|
||||
>
|
||||
<div
|
||||
class="member-list-alphabet-key"
|
||||
:style="{
|
||||
padding:
|
||||
state.manageType === 'searchRecord' ? '10rpx 30rpx' : '',
|
||||
}"
|
||||
v-if="alphabetItem?.memberList?.length > 0"
|
||||
:id="alphabetItem.key"
|
||||
:ref="
|
||||
(el) => {
|
||||
if (el) alphabetElementRefs[alphabetIndex] = el
|
||||
}
|
||||
"
|
||||
>
|
||||
<span class="text-[32rpx] font-regular">
|
||||
{{ alphabetItem.key }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="alphabetItem?.memberList?.length > 0">
|
||||
<div
|
||||
class="member-list-each"
|
||||
v-for="(item, index) in alphabetItem?.memberList"
|
||||
:key="index"
|
||||
>
|
||||
<tm-checkbox-group v-model="item.checkArr">
|
||||
<selectMemberItem
|
||||
:memberItem="item"
|
||||
@clickItem="handleClickItem(item)"
|
||||
:manageType="state.manageType"
|
||||
:itemStyle="
|
||||
state.manageType === 'searchRecord' ? 'list' : 'card'
|
||||
"
|
||||
>
|
||||
<template
|
||||
#left
|
||||
v-if="state.manageType !== 'searchRecord'"
|
||||
>
|
||||
<tm-checkbox
|
||||
:round="10"
|
||||
color="#46299d"
|
||||
:value="item.id"
|
||||
:disabled="item.is_mute === 1"
|
||||
></tm-checkbox>
|
||||
</template>
|
||||
</selectMemberItem>
|
||||
</tm-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #bottom v-if="state.manageType !== 'searchRecord'">
|
||||
<customBtn
|
||||
:isBottom="true"
|
||||
:btnText="$t('ok')"
|
||||
@clickBtn="confirmSilenceMember"
|
||||
></customBtn>
|
||||
</template>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import customInput from '@/components/custom-input/custom-input.vue'
|
||||
import selectMemberItem from '../components/select-member-item.vue'
|
||||
import customBtn from '@/components/custom-btn/custom-btn.vue'
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
||||
import { computed, onMounted, reactive, ref, watch, nextTick } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
|
||||
import { useDialogueStore } from '@/store'
|
||||
|
||||
const zPaging = ref()
|
||||
useZPaging(zPaging)
|
||||
|
||||
const dialogueStore = useDialogueStore()
|
||||
const state = reactive({
|
||||
searchText: '', //搜索内容
|
||||
manageType: '', //管理类型
|
||||
alphabet: [], //A-Z列表
|
||||
resultMemberList: [], //按A-Z整理后的人员列表
|
||||
currentAlphabet: 'A', //当前A-Z位置
|
||||
scrollDirection: '', //当前列表滚动方向
|
||||
isAssign: false, //是否指定view
|
||||
})
|
||||
const dialogueParams = reactive({
|
||||
memberList: computed(() => {
|
||||
const lowerCaseSearchText = state?.searchText.toLowerCase()
|
||||
return dialogueStore.members.filter((item) =>
|
||||
state?.searchText
|
||||
? item.nickname.toLowerCase().includes(lowerCaseSearchText)
|
||||
: true,
|
||||
)
|
||||
}),
|
||||
receiverId: computed(() => dialogueStore.talk.receiver_id),
|
||||
})
|
||||
|
||||
watch(
|
||||
() => dialogueParams?.memberList,
|
||||
(newMemberList) => {
|
||||
assembleAlphabetMmeberList(newMemberList)
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
//获取A-Z tag元素
|
||||
const alphabetElementRefs = ref([])
|
||||
//观察者
|
||||
let observer
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
if (options.manageType) {
|
||||
state.manageType = options.manageType
|
||||
assembleAlphabetMmeberList(dialogueParams?.memberList)
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
dialogueParams.memberList.forEach((ele) => {
|
||||
ele.checkArr = []
|
||||
})
|
||||
const options = {
|
||||
root: null, // 使用浏览器窗口作为根容器
|
||||
threshold: 1.0, // 当元素100%离开视口时触发
|
||||
}
|
||||
observer = new IntersectionObserver(handleIntersection, options)
|
||||
nextTick(() => {
|
||||
watch(
|
||||
alphabetElementRefs,
|
||||
(newAlphabetElementRefs) => {
|
||||
if (Array.isArray(newAlphabetElementRefs)) {
|
||||
newAlphabetElementRefs.forEach((el, index) => {
|
||||
observeElement(el, index)
|
||||
})
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
)
|
||||
if (alphabetElementRefs.value.length > 0) {
|
||||
alphabetElementRefs.value.forEach((el, index) =>
|
||||
observeElement(el, index),
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 观察者函数
|
||||
const handleIntersection = (entries) => {
|
||||
if (state.isAssign) {
|
||||
state.isAssign = false
|
||||
return
|
||||
}
|
||||
entries.forEach((entry) => {
|
||||
if (!entry.isIntersecting && state.scrollDirection === 'down') {
|
||||
state.currentAlphabet = entry.target.id
|
||||
} else if (entry.isIntersecting && state.scrollDirection === 'up') {
|
||||
if (state?.alphabet?.length > 1) {
|
||||
state?.alphabet.forEach((item, index) => {
|
||||
if (item === entry.target.id && index > 0) {
|
||||
state.currentAlphabet = state?.alphabet[index - 1]
|
||||
}
|
||||
})
|
||||
} else {
|
||||
state.currentAlphabet = entry.target.id
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//观察元素
|
||||
const observeElement = (el, index) => {
|
||||
if (el && observer) {
|
||||
observer.observe(el)
|
||||
}
|
||||
}
|
||||
|
||||
//输入搜索文本
|
||||
const inputSearchText = (e) => {
|
||||
// console.log(e)
|
||||
state.searchText = e
|
||||
}
|
||||
|
||||
//点击item
|
||||
const handleClickItem = (item) => {
|
||||
dialogueParams.memberList.forEach((ele) => {
|
||||
if (ele.id == item.id) {
|
||||
ele.checkArr = ele.checkArr?.length > 0 ? [] : [item.id]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//点击确认要禁言的成员
|
||||
const confirmSilenceMember = () => {
|
||||
let selectedUserIds = ''
|
||||
dialogueParams.memberList.forEach((ele) => {
|
||||
if (ele.checkArr?.length > 0) {
|
||||
if (!selectedUserIds) {
|
||||
selectedUserIds = ele.checkArr[0]
|
||||
} else {
|
||||
selectedUserIds += ',' + ele.checkArr[0]
|
||||
}
|
||||
}
|
||||
})
|
||||
console.log(selectedUserIds)
|
||||
if (selectedUserIds) {
|
||||
let params = {
|
||||
mode: 1, //1禁言2解禁
|
||||
group_id: dialogueParams.receiverId, //群id
|
||||
user_ids: selectedUserIds, //用户ids
|
||||
}
|
||||
console.log(params)
|
||||
}
|
||||
}
|
||||
|
||||
//组装A-Z排序的人员列表
|
||||
const assembleAlphabetMmeberList = (newMemberList) => {
|
||||
if (state.manageType === 'searchRecord') {
|
||||
const resultMemberList = ref([])
|
||||
const alphabet = Array.from({ length: 26 }, (_, i) =>
|
||||
String.fromCharCode(i + 65),
|
||||
)
|
||||
let tempAlphabet = []
|
||||
alphabet.forEach((letter) => {
|
||||
const matchedItems = newMemberList.filter((item) => item.key === letter)
|
||||
if (matchedItems.length > 0) {
|
||||
tempAlphabet.push(letter)
|
||||
}
|
||||
resultMemberList.value.push({
|
||||
key: letter,
|
||||
memberList: matchedItems.length ? matchedItems : [],
|
||||
})
|
||||
})
|
||||
state.alphabet = tempAlphabet
|
||||
state.resultMemberList = resultMemberList
|
||||
} else {
|
||||
state.resultMemberList = [
|
||||
{
|
||||
key: '',
|
||||
memberList: newMemberList,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
//滚动到指定的view
|
||||
const scrollToView = (alphabet) => {
|
||||
state.currentAlphabet = alphabet
|
||||
state.isAssign = true
|
||||
console.log()
|
||||
zPaging.value?.scrollIntoViewById(
|
||||
alphabet,
|
||||
document.getElementById('topArea').clientHeight
|
||||
? document.getElementById('topArea').clientHeight - 1
|
||||
: 80,
|
||||
)
|
||||
}
|
||||
|
||||
//监听列表滚动
|
||||
const onScroll = (e) => {
|
||||
if (e.detail.deltaY < 0) {
|
||||
state.scrollDirection = 'down'
|
||||
} else if (e.detail.deltaY > 0) {
|
||||
state.scrollDirection = 'up'
|
||||
} else {
|
||||
state.scrollDirection = ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.outer-layer {
|
||||
flex: 1;
|
||||
background-image: url('@/static/image/clockIn/z3280@3x.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.select-members {
|
||||
padding: 20rpx 32rpx;
|
||||
.search-member {
|
||||
padding: 22rpx 16rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
.member-list {
|
||||
.member-list-alphabet-anchor-point {
|
||||
position: fixed;
|
||||
right: 32rpx;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.member-list-alphabet-anchor-point-each {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 0 14rpx;
|
||||
span {
|
||||
width: 52rpx;
|
||||
text-align: center;
|
||||
line-height: 44rpx;
|
||||
color: $theme-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
.member-list-alphabet {
|
||||
.member-list-alphabet-key {
|
||||
background-color: #f3f3f3;
|
||||
span {
|
||||
line-height: 44rpx;
|
||||
color: $theme-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
639
src/pages/chatSettings/index.vue
Normal file
@ -0,0 +1,639 @@
|
||||
<template>
|
||||
<div class="outer-layer chat-settings-page">
|
||||
<div class="root">
|
||||
<ZPaging ref="zPaging" :show-scrollbar="false">
|
||||
<template #top>
|
||||
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span class="text-[34rpx] font-medium">
|
||||
{{ $t('index.chat.settings') }}
|
||||
</span>
|
||||
</div>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div class="chat-settings">
|
||||
<div class="chat-group-base-infos chat-settings-card">
|
||||
<div class="base-info-avatar" @click="toEditAvatarPage">
|
||||
<img :src="groupAvatar" />
|
||||
</div>
|
||||
<div class="base-info">
|
||||
<div class="base-info-name">
|
||||
<span class="text-[32rpx] font-medium">{{ groupName }}</span>
|
||||
<span class="base-info_num text-[32rpx] font-medium">
|
||||
{{ '(' + groupNum + ')' }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="base-info-tag"
|
||||
:style="{
|
||||
borderColor:
|
||||
groupTypeMapping[groupParams?.groupInfo?.group_type]
|
||||
?.result_type_color,
|
||||
}"
|
||||
>
|
||||
<span
|
||||
class="text-[24rpx] font-medium"
|
||||
:style="{
|
||||
color:
|
||||
groupTypeMapping[groupParams?.groupInfo?.group_type]
|
||||
?.result_type_color,
|
||||
}"
|
||||
>
|
||||
{{ groupType }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="base-info-edit" @click="toEditGroupInfoPage">
|
||||
<img src="/src/static/image/chatSettings/edit-btn.png" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-group-members chat-group-infos chat-settings-card">
|
||||
<div
|
||||
class="chat-group-infos-each"
|
||||
v-for="(item, index) in state.chatGroupMembers"
|
||||
:key="index"
|
||||
>
|
||||
<settingFormItem
|
||||
:item="item"
|
||||
@toManagePage="toManagePage"
|
||||
></settingFormItem>
|
||||
<groupMemberList
|
||||
:memberList="dialogueParams?.memberList"
|
||||
:memberListsLimit="15"
|
||||
></groupMemberList>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-group-infos chat-settings-card">
|
||||
<div
|
||||
class="chat-group-infos-each"
|
||||
v-for="(item, index) in state.chatGroupInfos"
|
||||
:key="index"
|
||||
>
|
||||
<settingFormItem
|
||||
:item="item"
|
||||
@toManagePage="toManagePage"
|
||||
></settingFormItem>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-records-search chat-settings-card">
|
||||
<customInput></customInput>
|
||||
<div class="record-search-types">
|
||||
<div
|
||||
class="record-search-types-each"
|
||||
v-for="(item, index) in state.recordSearchTypeList"
|
||||
:key="index"
|
||||
@click="toSearchByConditionPage(index)"
|
||||
>
|
||||
<img class="record-search-types-icon" :src="item.typeIcon" />
|
||||
<span class="text-[24rpx] font-regular">{{ item.value }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-group-infos chat-settings-card">
|
||||
<div
|
||||
class="chat-group-infos-each"
|
||||
v-for="(item, index) in state.chatSettings"
|
||||
:key="index"
|
||||
>
|
||||
<settingFormItem
|
||||
:item="item"
|
||||
@toManagePage="toManagePage"
|
||||
:sessionInfo="state?.sessionInfo"
|
||||
@changeSwitch="changeSwitch"
|
||||
></settingFormItem>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-group-infos chat-settings-card">
|
||||
<div
|
||||
class="chat-group-infos-each"
|
||||
v-for="(item, index) in state.chatManagement"
|
||||
:key="index"
|
||||
>
|
||||
<settingFormItem
|
||||
:item="item"
|
||||
@toManagePage="toManagePage"
|
||||
></settingFormItem>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear-chat-record-btn chat-settings-card">
|
||||
<div class="clear-chat-record-btn-each">
|
||||
<span class="text-[32rpx] font-regular">
|
||||
{{ $t('chat.settings.clearChatRecord') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="clear-chat-record-btn-each">
|
||||
<span class="text-[32rpx] font-regular">
|
||||
{{ $t('group.disband.btn') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="clear-chat-record-btn-each">
|
||||
<span class="text-[32rpx] font-regular">
|
||||
{{ $t('group.quit.btn') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import zu4992 from '@/static/image/chatList/zu4992@2x.png'
|
||||
import zu4991 from '@/static/image/chatList/zu4991@2x.png'
|
||||
import zu4989 from '@/static/image/chatList/zu4989@2x.png'
|
||||
import zu5296 from '@/static/image/chatList/zu5296@2x.png'
|
||||
import recordSearchTypeIcon_groupMember from '@/static/image/chatSettings/recordSearchTypeGroupMembers.png'
|
||||
import recordSearchTypeIcon_date from '@/static/image/chatSettings/recordSearchTypeDate.png'
|
||||
import recordSearchTypeIcon_imgAndVideo from '@/static/image/chatSettings/recordSearchTypeImgAndVideo.png'
|
||||
import recordSearchTypeIcon_files from '@/static/image/chatSettings/recordSearchTypeFiles.png'
|
||||
import recordSearchTypeIcon_link from '@/static/image/chatSettings/recordSearchTypeLink.png'
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import settingFormItem from './components/settingFormItem.vue'
|
||||
import groupMemberList from './components/groupMembersList.vue'
|
||||
import { computed, onMounted, reactive } from 'vue'
|
||||
import {
|
||||
useUserStore,
|
||||
useTalkStore,
|
||||
useDialogueStore,
|
||||
useGroupStore,
|
||||
} from '@/store'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ServeTopTalkList, ServeSetNotDisturb } from '@/api/chat/index'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
import customInput from '@/components/custom-input/custom-input.vue'
|
||||
const userStore = useUserStore()
|
||||
const talkStore = useTalkStore()
|
||||
const dialogueStore = useDialogueStore()
|
||||
const dialogueParams = reactive({
|
||||
uid: computed(() => userStore.uid),
|
||||
index_name: computed(() => dialogueStore.index_name),
|
||||
type: computed(() => dialogueStore.talk.talk_type),
|
||||
receiver_id: computed(() => dialogueStore.talk.receiver_id),
|
||||
username: computed(() => dialogueStore.talk.username),
|
||||
online: computed(() => dialogueStore.online),
|
||||
keyboard: computed(() => dialogueStore.keyboard),
|
||||
num: computed(() => dialogueStore.members.length),
|
||||
memberList: computed(() => dialogueStore.members),
|
||||
})
|
||||
const talkParams = reactive({
|
||||
topItems: computed(() => talkStore.topItems),
|
||||
disturbItems: computed(() => talkStore.disturbItems),
|
||||
})
|
||||
const groupStore = useGroupStore()
|
||||
const groupParams = reactive({
|
||||
groupInfo: computed(() => groupStore.groupInfo),
|
||||
groupNotice: computed(() => groupStore.groupNotice),
|
||||
})
|
||||
const state = reactive({
|
||||
chatGroupMembers: [], //群成员form-item
|
||||
chatGroupInfos: [], //群聊信息
|
||||
recordSearchTypeList: [], //聊天记录搜索类型
|
||||
chatSettings: [], //群聊设置
|
||||
chatManagement: [], //群聊管理
|
||||
groupId: '', //群id
|
||||
sessionId: '', //会话id
|
||||
})
|
||||
|
||||
onLoad(async (options) => {
|
||||
console.log(dialogueParams)
|
||||
if (options.groupId) {
|
||||
console.log(options.groupId)
|
||||
state.groupId = Number(options.groupId)
|
||||
await groupStore.ServeGroupDetail()
|
||||
await groupStore.ServeGetGroupNotices()
|
||||
updateGroupInfos()
|
||||
}
|
||||
if (options.sessionId) {
|
||||
state.sessionId = Number(options.sessionId)
|
||||
if (talkParams.topItems.length > 0) {
|
||||
talkParams.topItems.forEach((item) => {
|
||||
if (item.id == options.sessionId) {
|
||||
state.sessionInfo = item
|
||||
}
|
||||
})
|
||||
}
|
||||
if (talkParams.disturbItems.length > 0) {
|
||||
talkParams.disturbItems.forEach((item) => {
|
||||
if (item.id == options.sessionId) {
|
||||
state.sessionInfo = item
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
updateGroupInfos()
|
||||
state.recordSearchTypeList = [
|
||||
{
|
||||
value: t('chat.settings.groupMember'),
|
||||
typeIcon: recordSearchTypeIcon_groupMember,
|
||||
},
|
||||
{
|
||||
value: t('record.searchType.date'),
|
||||
typeIcon: recordSearchTypeIcon_date,
|
||||
},
|
||||
{
|
||||
value: t('record.searchType.imgAndVideo'),
|
||||
typeIcon: recordSearchTypeIcon_imgAndVideo,
|
||||
},
|
||||
{
|
||||
value: t('record.searchType.files'),
|
||||
typeIcon: recordSearchTypeIcon_files,
|
||||
},
|
||||
{
|
||||
value: t('record.searchType.link'),
|
||||
typeIcon: recordSearchTypeIcon_link,
|
||||
},
|
||||
]
|
||||
state.chatSettings = [
|
||||
{
|
||||
label: t('chat.settings.topSession'),
|
||||
hasPointer: false,
|
||||
value: '',
|
||||
subValue: '',
|
||||
customInfo: 'switch',
|
||||
},
|
||||
{
|
||||
label: t('chat.settings.messageNoDisturb'),
|
||||
hasPointer: false,
|
||||
value: '',
|
||||
subValue: '',
|
||||
customInfo: 'switch',
|
||||
},
|
||||
]
|
||||
state.chatManagement = [
|
||||
{
|
||||
label: t('chat.settings.groupGag'),
|
||||
hasPointer: true,
|
||||
value: '',
|
||||
subValue: '',
|
||||
customInfo: '',
|
||||
},
|
||||
{
|
||||
label: t('chat.settings.groupAdmin'),
|
||||
hasPointer: true,
|
||||
value: '',
|
||||
subValue: '总经理室-总经理,苏州站-出纳,常熟站…',
|
||||
customInfo: '',
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
//群头像
|
||||
const groupAvatar = computed(() => {
|
||||
return (
|
||||
groupParams?.groupInfo?.avatar ||
|
||||
groupTypeMapping[groupParams?.groupInfo?.group_type]?.defaultImg
|
||||
)
|
||||
})
|
||||
|
||||
//群名称
|
||||
const groupName = computed(() => {
|
||||
return groupParams?.groupInfo?.group_name
|
||||
})
|
||||
|
||||
//群人数
|
||||
const groupNum = computed(() => {
|
||||
return groupParams?.groupInfo?.group_num || 0
|
||||
})
|
||||
|
||||
// 映射表-根据groupType设置对应值
|
||||
const groupTypeMapping = {
|
||||
0: {
|
||||
defaultImg: 'textImg',
|
||||
},
|
||||
1: {
|
||||
defaultImg: zu4992,
|
||||
},
|
||||
2: {
|
||||
result_type: t('index.mine.department'),
|
||||
result_type_color: '#377EC6',
|
||||
defaultImg: zu4989,
|
||||
},
|
||||
3: {
|
||||
result_type: t('index.mine.project'),
|
||||
result_type_color: '#C1681C',
|
||||
defaultImg: zu4991,
|
||||
},
|
||||
4: {
|
||||
result_type: t('index.type.company'),
|
||||
result_type_color: '#7A58DE',
|
||||
defaultImg: zu5296,
|
||||
},
|
||||
}
|
||||
|
||||
//群类型
|
||||
const groupType = computed(() => {
|
||||
return groupTypeMapping[groupParams?.groupInfo?.group_type]?.result_type || ''
|
||||
})
|
||||
|
||||
//更新群信息
|
||||
const updateGroupInfos = () => {
|
||||
state.chatGroupMembers = [
|
||||
{
|
||||
label: t('chat.settings.groupMember'),
|
||||
hasPointer: true,
|
||||
value: '全部(' + groupNum.value + ')',
|
||||
subValue: '',
|
||||
customInfo: '',
|
||||
},
|
||||
]
|
||||
state.chatGroupInfos = [
|
||||
{
|
||||
label: t('chat.settings.groupName'),
|
||||
hasPointer: true,
|
||||
value: groupName.value,
|
||||
subValue: '',
|
||||
customInfo: '',
|
||||
},
|
||||
{
|
||||
label: t('chat.settings.groupNotice'),
|
||||
hasPointer: true,
|
||||
value: '',
|
||||
subValue: groupParams.groupNotice[0],
|
||||
customInfo: '',
|
||||
},
|
||||
{
|
||||
label: t('chat.settings.groupType'),
|
||||
hasPointer: false,
|
||||
value: groupType.value + '群',
|
||||
subValue: '',
|
||||
customInfo: '',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
//点击跳转到修改群信息页面
|
||||
const toEditGroupInfoPage = () => {
|
||||
uni.navigateTo({
|
||||
url:
|
||||
'/pages/chatSettings/groupManage/editGroupName?groupAvatar=' +
|
||||
groupAvatar.value,
|
||||
})
|
||||
}
|
||||
|
||||
//点击跳转到修改头像页面
|
||||
const toEditAvatarPage = () => {
|
||||
uni.navigateTo({
|
||||
url:
|
||||
'/pages/chatSettings/groupManage/editAvatar?groupAvatar=' +
|
||||
groupAvatar.value,
|
||||
})
|
||||
}
|
||||
|
||||
//点击跳转到管理页面
|
||||
const toManagePage = (label) => {
|
||||
console.log(label)
|
||||
if (label) {
|
||||
if (label === t('chat.settings.groupName')) {
|
||||
uni.navigateTo({
|
||||
url:
|
||||
'/pages/chatSettings/groupManage/editGroupName?groupAvatar=' +
|
||||
groupAvatar.value,
|
||||
})
|
||||
} else if (label === t('chat.settings.groupNotice')) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/chatSettings/groupManage/manageNotice',
|
||||
})
|
||||
} else if (label === t('chat.settings.groupMember')) {
|
||||
uni.navigateTo({
|
||||
url:
|
||||
'/pages/chatSettings/groupManage/manageGroupMembers?groupId=' +
|
||||
state.groupId,
|
||||
})
|
||||
} else if (label === t('chat.settings.groupGag')) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/chatSettings/groupManage/manageGroupSilence',
|
||||
})
|
||||
} else if (label === t('chat.settings.groupAdmin')) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/chatSettings/groupManage/manageGroupAdmin',
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//点击跳转到按条件搜索页
|
||||
const toSearchByConditionPage = (flag) => {
|
||||
let condition = ''
|
||||
if (flag == 0) {
|
||||
uni.navigateTo({
|
||||
url:
|
||||
'/pages/chatSettings/groupManage/selectMembers?manageType=searchRecord',
|
||||
})
|
||||
} else {
|
||||
if (flag == 1) {
|
||||
condition = 'date'
|
||||
}
|
||||
uni.navigateTo({
|
||||
url:
|
||||
'/pages/search/searchByCondition/index?condition=' +
|
||||
condition +
|
||||
'&receiver_id=' +
|
||||
state.groupId,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//切换开关选择
|
||||
const changeSwitch = (switchStatus, label) => {
|
||||
let params
|
||||
let resp
|
||||
if (label == t('chat.settings.topSession')) {
|
||||
params = {
|
||||
list_id: state.sessionId, //聊天会话的id
|
||||
type: switchStatus ? 1 : 2,
|
||||
}
|
||||
resp = ServeTopTalkList(params)
|
||||
} else if (label == t('chat.settings.messageNoDisturb')) {
|
||||
params = {
|
||||
talk_type: dialogueParams.type, //1私聊;2群聊
|
||||
receiver_id: dialogueParams.receiver_id, //接收人id或群id
|
||||
is_disturb: switchStatus ? 1 : 0, //是否开启免打扰,0不免打扰,1免打扰
|
||||
}
|
||||
resp = ServeSetNotDisturb(params)
|
||||
}
|
||||
console.log(resp)
|
||||
resp.then(({ code, data }) => {
|
||||
console.log(data)
|
||||
if (code == 200) {
|
||||
if (label == t('chat.settings.topSession')) {
|
||||
talkStore.updateItem({
|
||||
index_name: dialogueParams.index_name,
|
||||
is_top: switchStatus ? 1 : 2,
|
||||
})
|
||||
} else if (label == t('chat.settings.messageNoDisturb')) {
|
||||
talkStore.updateItem({
|
||||
index_name: dialogueParams.index_name,
|
||||
is_disturb: switchStatus ? 1 : 0,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
}
|
||||
})
|
||||
|
||||
resp.catch(() => {})
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.outer-layer {
|
||||
flex: 1;
|
||||
background-image: url('@/static/image/clockIn/z3280@3x.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.chat-settings-page {
|
||||
.navBar-title {
|
||||
span {
|
||||
line-height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-settings {
|
||||
padding: 0 32rpx 36rpx;
|
||||
width: 100%;
|
||||
|
||||
.chat-settings-card {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
margin: 20rpx 0 0;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
|
||||
}
|
||||
|
||||
.chat-group-base-infos {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx 40rpx 32rpx 20rpx;
|
||||
|
||||
.base-info-avatar {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.base-info {
|
||||
width: 100%;
|
||||
margin: 0 30rpx;
|
||||
.base-info-name {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
span {
|
||||
line-height: 44rpx;
|
||||
color: $theme-text;
|
||||
}
|
||||
.base-info_num {
|
||||
line-height: 44rpx;
|
||||
}
|
||||
}
|
||||
.base-info-tag {
|
||||
border: 2rpx solid #7a58de;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2rpx 14rpx;
|
||||
margin: 10rpx 0 0;
|
||||
border-radius: 8rpx;
|
||||
width: 80rpx;
|
||||
span {
|
||||
flex-shrink: 0;
|
||||
color: #7a58de;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.base-info-edit {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
flex-shrink: 0;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chat-group-members {
|
||||
}
|
||||
|
||||
.chat-group-infos {
|
||||
padding: 0 16rpx;
|
||||
.chat-group-infos-each {
|
||||
padding: 32rpx 14rpx;
|
||||
border-bottom: 1px solid $theme-border-color;
|
||||
}
|
||||
.chat-group-infos-each:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-records-search {
|
||||
padding: 22rpx 16rpx;
|
||||
|
||||
.record-search-types {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
.record-search-types-each {
|
||||
width: calc(100% / 4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 36rpx 0 0;
|
||||
.record-search-types-icon {
|
||||
width: 106rpx;
|
||||
height: 106rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
span {
|
||||
line-height: 34px;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.clear-chat-record-btn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.clear-chat-record-btn-each {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32rpx 16rpx;
|
||||
width: calc(100% - 32rpx);
|
||||
border-bottom: 1px solid $theme-border-color;
|
||||
|
||||
span {
|
||||
line-height: 44rpx;
|
||||
color: #cf3050;
|
||||
}
|
||||
}
|
||||
.clear-chat-record-btn-each:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<template v-slot:right>
|
||||
<div class="mr-[36rpx]">
|
||||
<tm-icon color="rgb(51, 51, 51)" :font-size="36" name="tmicon-gengduo"></tm-icon>
|
||||
<tm-icon color="rgb(51, 51, 51)" :font-size="36" name="tmicon-gengduo" @click="toChatSettingsPage"></tm-icon>
|
||||
</div>
|
||||
</template>
|
||||
</tm-navbar>
|
||||
@ -228,8 +228,7 @@ import zu6053 from "@/static/image/chatList/zu6053@2x.png"
|
||||
import deepBubble from "@/components/deep-bubble/deep-bubble.vue"
|
||||
import {isRevoke } from './menu'
|
||||
import useConfirm from '@/components/x-confirm/useConfirm.js'
|
||||
|
||||
|
||||
import { onLoad as uniOnload } from '@dcloudio/uni-app'
|
||||
|
||||
Quill.register('formats/emoji', EmojiBlot)
|
||||
|
||||
@ -260,6 +259,13 @@ const state = ref({
|
||||
isOpenFilePanel: false,
|
||||
showWin: false,
|
||||
onfocusItem: null,
|
||||
sessionId: ''
|
||||
})
|
||||
|
||||
uniOnload((options) => {
|
||||
if (options.sessionId) {
|
||||
state.sessionId = options.sessionId
|
||||
}
|
||||
})
|
||||
|
||||
const handleEmojiPanel = () => {
|
||||
@ -680,6 +686,13 @@ const initData = async () => {
|
||||
zpagingRef.value?.complete(records.value)
|
||||
}
|
||||
|
||||
//点击跳转到聊天设置页面
|
||||
const toChatSettingsPage = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/chatSettings/index?groupId=' + talkParams?.receiver_id + '&sessionId=' + state.sessionId
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
initData()
|
||||
})
|
||||
|
@ -139,7 +139,7 @@ const cellClick = () => {
|
||||
});
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: "/pages/dialog/index",
|
||||
url: '/pages/dialog/index?sessionId=' + props.data.id,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
||||
</tm-navbar>
|
||||
</div>
|
||||
<div class="root">
|
||||
<div class="searchRoot">
|
||||
<div class="searchRoot" @click="toSearchPage">
|
||||
<tm-input
|
||||
placeholder="请输入…"
|
||||
color="#F9F9FD"
|
||||
@ -111,6 +111,12 @@ const creatGroupChat = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const toSearchPage = () => {
|
||||
uni.navigateTo({
|
||||
url: "/pages/search/index",
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => talkStore,
|
||||
(newValue, oldValue) => {
|
||||
|
70
src/pages/search/components/highLightText.vue
Normal file
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<span>
|
||||
<template v-for="(part, index) in parts" :key="index">
|
||||
<span v-if="part.highlighted" :class="highlightClass">
|
||||
{{ part.text }}
|
||||
</span>
|
||||
<span v-else>{{ part.text }}</span>
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
searchText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
highlightClass: {
|
||||
type: String,
|
||||
default: 'highlight',
|
||||
},
|
||||
})
|
||||
|
||||
const escapedSearchText = computed(() =>
|
||||
String(props.searchText).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),
|
||||
)
|
||||
|
||||
const pattern = computed(() => new RegExp(escapedSearchText.value, 'gi'))
|
||||
|
||||
const parts = computed(() => {
|
||||
if (!props.searchText || !props.text)
|
||||
return [{ text: props.text, highlighted: false }];
|
||||
|
||||
const result = [];
|
||||
let currentIndex = 0;
|
||||
const escapedSearchTextValue = escapedSearchText.value;
|
||||
const searchPattern = new RegExp(`(${escapedSearchTextValue})`, 'gi');
|
||||
|
||||
props.text.replace(searchPattern, (match, p1, offset) => {
|
||||
// 添加非高亮文本
|
||||
if (currentIndex < offset) {
|
||||
result.push({ text: props.text.slice(currentIndex, offset), highlighted: false });
|
||||
}
|
||||
// 添加高亮文本
|
||||
result.push({ text: p1, highlighted: true });
|
||||
// 更新当前索引
|
||||
currentIndex = offset + p1.length;
|
||||
return p1; // 这个返回值不影响最终结果,只是replace方法的要求
|
||||
});
|
||||
|
||||
// 添加剩余的非高亮文本(如果有的话)
|
||||
if (currentIndex < props.text.length) {
|
||||
result.push({ text: props.text.slice(currentIndex), highlighted: false });
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.highlight {
|
||||
color: #7a58de;
|
||||
}
|
||||
</style>
|
331
src/pages/search/components/searchItem.vue
Normal file
@ -0,0 +1,331 @@
|
||||
<template>
|
||||
<div
|
||||
class="search-item"
|
||||
v-if="resultName"
|
||||
:style="
|
||||
props.searchResultKey === 'talk_record_infos_receiver'
|
||||
? 'margin: 24rpx 0 0'
|
||||
: ''
|
||||
"
|
||||
>
|
||||
<div class="avatar-img">
|
||||
<img v-if="avatarImg !== 'textImg'" :src="avatarImg" />
|
||||
<span v-if="avatarImg === 'textImg'" class="text-[32rpx] font-bold">
|
||||
{{ imgText }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="result-info">
|
||||
<div
|
||||
class="info-name"
|
||||
:class="searchRecordDetail ? 'info-name-searchRecordDetail' : ''"
|
||||
>
|
||||
<HighlightText
|
||||
:class="
|
||||
searchRecordDetail
|
||||
? 'text-[24rpx] font-medium'
|
||||
: 'text-[32rpx] font-medium'
|
||||
"
|
||||
:text="resultName"
|
||||
:searchText="props.searchText"
|
||||
/>
|
||||
<div class="info_num" v-if="groupNum">
|
||||
<span class="text-[32rpx] font-medium">
|
||||
{{ '(' + groupNum + ')' }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="info-tag"
|
||||
v-if="resultType && !searchRecordDetail"
|
||||
:style="'border-color:' + resultTypeColor"
|
||||
>
|
||||
<span
|
||||
class="text-[24rpx] font-medium"
|
||||
:style="'color:' + resultTypeColor"
|
||||
>
|
||||
{{ resultType }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="searchRecordDetail && chatRecordCreatedAt">
|
||||
<span class="text-[24rpx] font-medium">
|
||||
{{ chatRecordCreatedAt }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="info-detail"
|
||||
v-if="resultDetail"
|
||||
:class="searchRecordDetail ? 'info-detail-searchRecordDetail' : ''"
|
||||
>
|
||||
<HighlightText
|
||||
class="text-[28rpx] font-regular"
|
||||
:text="resultDetail"
|
||||
:searchText="props.searchText"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-item-pointer" v-if="pointerIconSrc">
|
||||
<img :src="pointerIconSrc" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import zu4992 from '@/static/image/chatList/zu4992@2x.png'
|
||||
import zu4991 from '@/static/image/chatList/zu4991@2x.png'
|
||||
import zu4989 from '@/static/image/chatList/zu4989@2x.png'
|
||||
import zu5296 from '@/static/image/chatList/zu5296@2x.png'
|
||||
import {
|
||||
ref,
|
||||
watch,
|
||||
computed,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
reactive,
|
||||
defineProps,
|
||||
} from 'vue'
|
||||
import HighlightText from './highLightText.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { beautifyTime } from '@/utils/datetime'
|
||||
const { t } = useI18n()
|
||||
const props = defineProps({
|
||||
searchItem: Object | Number,
|
||||
searchResultKey: String,
|
||||
searchText: String, //搜索内容
|
||||
searchRecordDetail: Boolean, //是否是搜索聊天记录详情
|
||||
pointerIconSrc: String, //箭头图标
|
||||
})
|
||||
// 映射表-查找对应结构下的属性名
|
||||
const keyMapping = {
|
||||
user_infos: { avatar: 'avatar', name: 'nickname' },
|
||||
group_infos: { avatar: 'avatar', name: 'name', group_num: 'group_num' },
|
||||
group_member_infos: {
|
||||
avatar: 'group_avatar',
|
||||
name: 'group_name',
|
||||
detailKey: 'user_name',
|
||||
group_num: 'group_num',
|
||||
},
|
||||
combinedGroup: {
|
||||
avatar: props.searchItem?.groupTempType
|
||||
? props.searchItem?.groupTempType === 'group_infos'
|
||||
? 'avatar'
|
||||
: props.searchItem?.groupTempType === 'group_member_infos'
|
||||
? 'group_avatar'
|
||||
: ''
|
||||
: '',
|
||||
name: props.searchItem?.groupTempType
|
||||
? props.searchItem?.groupTempType === 'group_infos'
|
||||
? 'name'
|
||||
: props.searchItem?.groupTempType === 'group_member_infos'
|
||||
? 'group_name'
|
||||
: ''
|
||||
: '',
|
||||
detailKey: props.searchItem?.groupTempType
|
||||
? props.searchItem?.groupTempType === 'group_member_infos'
|
||||
? 'user_name'
|
||||
: ''
|
||||
: '',
|
||||
group_num: props.searchItem?.groupTempType
|
||||
? props.searchItem?.groupTempType === 'group_infos'
|
||||
? 'group_num'
|
||||
: props.searchItem?.groupTempType === 'group_member_infos'
|
||||
? 'group_num'
|
||||
: ''
|
||||
: '',
|
||||
},
|
||||
general_infos: {
|
||||
avatar: 'receiver_avatar',
|
||||
name: 'receiver_name',
|
||||
detailKey: 'count',
|
||||
group_num: 'group_num',
|
||||
},
|
||||
talk_record_infos: {
|
||||
avatar: 'user_avatar',
|
||||
name: 'user_name',
|
||||
detailKey: 'extra',
|
||||
created_at: 'created_at',
|
||||
},
|
||||
talk_record_infos_receiver: {
|
||||
avatar: 'receiver_avatar',
|
||||
name: 'receiver_name',
|
||||
group_num: 'group_num',
|
||||
},
|
||||
}
|
||||
//获取key对应值
|
||||
const getKeyValue = (keys) => {
|
||||
let keyValue = ''
|
||||
if (keys) {
|
||||
keyValue = props?.searchItem ? props?.searchItem[keys] : ''
|
||||
}
|
||||
return keyValue
|
||||
}
|
||||
//头像
|
||||
const avatarImg = computed(() => {
|
||||
let avatar = getKeyValue(keyMapping[props.searchResultKey]?.avatar)
|
||||
if (!avatar) {
|
||||
avatar = groupTypeMapping[props.searchItem?.group_type]?.defaultImg
|
||||
}
|
||||
return avatar
|
||||
})
|
||||
//名称
|
||||
const resultName = computed(() => {
|
||||
return getKeyValue(keyMapping[props.searchResultKey]?.name)
|
||||
})
|
||||
//文字头像
|
||||
const imgText = computed(() => {
|
||||
return resultName.value.length >= 2
|
||||
? resultName.value.slice(-2)
|
||||
: resultName.value
|
||||
})
|
||||
// 映射表-根据groupType设置对应值
|
||||
const groupTypeMapping = {
|
||||
0: {
|
||||
defaultImg: 'textImg',
|
||||
},
|
||||
1: {
|
||||
defaultImg: zu4992,
|
||||
},
|
||||
2: {
|
||||
result_type: t('index.mine.department'),
|
||||
result_type_color: '#377EC6',
|
||||
defaultImg: zu4989,
|
||||
},
|
||||
3: {
|
||||
result_type: t('index.mine.project'),
|
||||
result_type_color: '#C1681C',
|
||||
defaultImg: zu4991,
|
||||
},
|
||||
4: {
|
||||
result_type: t('index.type.company'),
|
||||
result_type_color: '#7A58DE',
|
||||
defaultImg: zu5296,
|
||||
},
|
||||
}
|
||||
//群人数
|
||||
const groupNum = computed(() => {
|
||||
return getKeyValue(keyMapping[props.searchResultKey]?.group_num)
|
||||
})
|
||||
//群类型tag
|
||||
const resultType = computed(() => {
|
||||
return groupTypeMapping[props.searchItem?.group_type]?.result_type
|
||||
})
|
||||
//群类型tag颜色
|
||||
const resultTypeColor = computed(() => {
|
||||
return groupTypeMapping[props.searchItem?.group_type]?.result_type_color
|
||||
})
|
||||
//搜索聊天记录详情-时间
|
||||
const chatRecordCreatedAt = computed(() => {
|
||||
let created_at = getKeyValue(keyMapping[props.searchResultKey]?.created_at)
|
||||
return beautifyTime(created_at)
|
||||
})
|
||||
//详细内容
|
||||
const resultDetail = computed(() => {
|
||||
let result_detail =
|
||||
props.searchItem[keyMapping[props.searchResultKey]?.detailKey]
|
||||
switch (keyMapping[props.searchResultKey]?.detailKey) {
|
||||
case 'count':
|
||||
result_detail = result_detail + t('search.chat.count')
|
||||
break
|
||||
case 'user_name':
|
||||
result_detail = t('search.result.include') + result_detail
|
||||
break
|
||||
case 'extra':
|
||||
result_detail = props.searchItem?.extra
|
||||
break
|
||||
default:
|
||||
result_detail = ''
|
||||
}
|
||||
return result_detail
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.search-item:nth-child(1) {
|
||||
border-top: 1px solid $theme-border-color;
|
||||
}
|
||||
.search-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 22rpx 0 24rpx;
|
||||
border-bottom: 1px solid $theme-border-color;
|
||||
|
||||
.avatar-img {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
margin: 0 20rpx 0 0;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(to right, #674bbc, #46299d);
|
||||
flex-shrink: 0;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
span {
|
||||
color: #fff;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
}
|
||||
.result-info {
|
||||
width: 100%;
|
||||
.info-name {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
span {
|
||||
color: $theme-text;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
.info-tag {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2rpx 14rpx;
|
||||
border: 2rpx solid #000;
|
||||
border-radius: 6rpx;
|
||||
span {
|
||||
line-height: 34rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.info-name-searchRecordDetail {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
span {
|
||||
color: $theme-hint-text;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
}
|
||||
.info-detail {
|
||||
span {
|
||||
color: $theme-hint-text;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
.info-detail-searchRecordDetail {
|
||||
span {
|
||||
color: $theme-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
.search-item-pointer {
|
||||
width: 11rpx;
|
||||
height: 18rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
419
src/pages/search/components/searchList.vue
Normal file
@ -0,0 +1,419 @@
|
||||
<template>
|
||||
<div class="search-list">
|
||||
<ZPaging
|
||||
ref="zPaging"
|
||||
:show-scrollbar="false"
|
||||
v-model="state.searchResultList"
|
||||
@query="queryAllSearch"
|
||||
:default-page-no="state.pageNum"
|
||||
:default-page-size="props.searchResultPageSize"
|
||||
:loading-more-default-as-loading="true"
|
||||
:inside-more="true"
|
||||
:empty-view-img="'/src/static//image/search/search-no-data.png'"
|
||||
:empty-view-text="$t('search.hint')"
|
||||
:empty-view-img-style="{ width: '476rpx', height: '261rpx' }"
|
||||
:empty-view-title-style="{
|
||||
color: '#999999',
|
||||
margin: '-20rpx 0 0',
|
||||
'line-height': '40rpx',
|
||||
'font-size': '28rpx',
|
||||
'font-weight': 400,
|
||||
}"
|
||||
>
|
||||
<template #top>
|
||||
<div class="searchRoot">
|
||||
<customInput
|
||||
:searchText="state.searchText"
|
||||
:first_talk_record_infos="state.first_talk_record_infos"
|
||||
@inputSearchText="inputSearchText"
|
||||
></customInput>
|
||||
<span
|
||||
class="searchRoot_cancelBtn text-[32rpx] font-medium"
|
||||
@click="cancelSearch"
|
||||
>
|
||||
{{ $t('cancel') }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="search-record-detail" v-if="props.searchRecordDetail">
|
||||
<searchItem
|
||||
@click="
|
||||
clickSearchItem(
|
||||
'talk_record_infos_receiver',
|
||||
state?.first_talk_record_infos,
|
||||
)
|
||||
"
|
||||
searchResultKey="talk_record_infos_receiver"
|
||||
:searchItem="state?.first_talk_record_infos"
|
||||
:pointerIconSrc="pointerIconSrc"
|
||||
></searchItem>
|
||||
</div>
|
||||
<div
|
||||
class="search-result"
|
||||
:style="
|
||||
!state.searchText ? 'align-items:center;justify-content:center;' : ''
|
||||
"
|
||||
>
|
||||
<div class="search-result-list">
|
||||
<div
|
||||
class="search-result-each-part"
|
||||
v-for="(searchResultValue,
|
||||
searchResultKey,
|
||||
searchResultIndex) in state.searchResult"
|
||||
:key="searchResultKey"
|
||||
>
|
||||
<div
|
||||
class="search-result-part"
|
||||
v-if="
|
||||
Array.isArray(state?.searchResult[searchResultKey]) &&
|
||||
state?.searchResult[searchResultKey].length > 0 &&
|
||||
searchResultKey !== 'group_infos' &&
|
||||
searchResultKey !== 'group_member_infos'
|
||||
"
|
||||
>
|
||||
<div class="result-title">
|
||||
<span class="text-[28rpx] font-regular">
|
||||
{{ getResultKeysValue(searchResultKey) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="result-list">
|
||||
<div
|
||||
class="result-list-each"
|
||||
v-for="(item, index) in state?.searchResult[searchResultKey]"
|
||||
:key="index"
|
||||
>
|
||||
<searchItem
|
||||
@click="clickSearchItem(searchResultKey, item)"
|
||||
v-if="(props.listLimit && index < 3) || !props.listLimit"
|
||||
:searchResultKey="searchResultKey"
|
||||
:searchItem="item"
|
||||
:searchText="state.searchText"
|
||||
:searchRecordDetail="props.searchRecordDetail"
|
||||
></searchItem>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="result-has-more"
|
||||
v-if="getHasMoreResult(searchResultKey)"
|
||||
@click="toMoreResultPage(searchResultKey)"
|
||||
>
|
||||
<span class="text-[28rpx] font-regular">
|
||||
{{ getHasMoreResult(searchResultKey) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import customInput from '@/components/custom-input/custom-input.vue'
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import useZPaging from '@/uni_modules/z-paging/components/z-paging/js/hooks/useZPaging.js'
|
||||
import searchItem from './searchItem.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ref, reactive, defineEmits, defineProps, onMounted } from 'vue'
|
||||
import pointerIconSrc from '@/static/image/search/search-item-pointer.png'
|
||||
|
||||
const zPaging = ref()
|
||||
useZPaging(zPaging)
|
||||
|
||||
const emits = defineEmits([
|
||||
'toMoreResultPage',
|
||||
'lastIdChange',
|
||||
'clickSearchItem',
|
||||
])
|
||||
|
||||
const state = reactive({
|
||||
searchText: '', //搜索内容
|
||||
searchResultList: [], //搜素结果列表
|
||||
searchResult: null, //搜索结果
|
||||
pageNum: 1, //当前请求数据页数
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
searchResultPageSize: Number, //搜索结果每页数据量
|
||||
listLimit: Boolean, //是否限制列表内数据数量
|
||||
apiParams: String, //请求参数
|
||||
apiRequest: Function, //请求
|
||||
searchText: String, //搜索内容
|
||||
isPagination: Boolean, //是否分页
|
||||
searchRecordDetail: Boolean, //是否是搜索聊天记录的详情
|
||||
first_talk_record_infos: Object, //接受者信息
|
||||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
if (props.searchText) {
|
||||
state.searchText = props.searchText
|
||||
}
|
||||
})
|
||||
|
||||
//输入搜索文本
|
||||
const inputSearchText = (e) => {
|
||||
// console.log(e)
|
||||
if (e.trim() != state.searchText.trim()) {
|
||||
state.pageNum = 1
|
||||
emits('lastIdChange', 0, 0, 0)
|
||||
}
|
||||
state.searchText = e.trim()
|
||||
if (!e.trim()) {
|
||||
emits('lastIdChange', 0, 0, 0)
|
||||
}
|
||||
zPaging.value?.reload()
|
||||
}
|
||||
|
||||
// ES搜索聊天记录-主页搜索什么都有、指定用户、指定群、群与用户概览
|
||||
const queryAllSearch = (pageNum, searchResultPageSize) => {
|
||||
let params = {
|
||||
key: state.searchText, //关键字
|
||||
size: searchResultPageSize,
|
||||
}
|
||||
if (props.apiParams) {
|
||||
let apiParams = JSON.parse(decodeURIComponent(props.apiParams))
|
||||
params = Object.assign({}, params, apiParams)
|
||||
}
|
||||
const resp = props.apiRequest(params)
|
||||
resp.then(({ code, data }) => {
|
||||
console.log(data)
|
||||
if (code == 200) {
|
||||
if ((data.user_infos || []).length > 0) {
|
||||
;(data.user_infos || []).forEach((item) => {
|
||||
item.group_type = 0
|
||||
})
|
||||
}
|
||||
if ((data.group_infos || []).length > 0) {
|
||||
;(data.group_infos || []).forEach((item) => {
|
||||
item.group_type = item.type
|
||||
item.groupTempType = 'group_infos'
|
||||
})
|
||||
}
|
||||
if ((data.group_member_infos || []).length > 0) {
|
||||
;(data.group_member_infos || []).forEach((item) => {
|
||||
item.groupTempType = 'group_member_infos'
|
||||
})
|
||||
}
|
||||
if ((data.talk_record_infos || []).length > 0) {
|
||||
state.first_talk_record_infos = Object.assign(
|
||||
{},
|
||||
state.first_talk_record_infos,
|
||||
data.talk_record_infos[0],
|
||||
)
|
||||
;(data.talk_record_infos || []).forEach((item) => {
|
||||
item.group_type = 0
|
||||
})
|
||||
}
|
||||
let tempGeneral_infos = Array.isArray(data.general_infos)
|
||||
? [...data.general_infos]
|
||||
: data.general_infos
|
||||
delete data.general_infos
|
||||
data.combinedGroup = (data.group_infos || []).concat(
|
||||
data.group_member_infos || [],
|
||||
)
|
||||
data.general_infos = tempGeneral_infos
|
||||
let isEmpty = true
|
||||
let dataKeys = Object.keys(data)
|
||||
let paginationKey = ''
|
||||
dataKeys.forEach((item) => {
|
||||
if (Array.isArray(data[item]) && data[item].length > 0) {
|
||||
paginationKey = item
|
||||
isEmpty = false
|
||||
}
|
||||
})
|
||||
if (isEmpty) {
|
||||
if (pageNum == 1) {
|
||||
zPaging.value?.complete([])
|
||||
} else {
|
||||
data = state.searchResult
|
||||
zPaging.value?.complete([data])
|
||||
}
|
||||
} else {
|
||||
if (props.isPagination) {
|
||||
if (
|
||||
paginationKey &&
|
||||
Array.isArray(
|
||||
(state?.searchResult && state?.searchResult[paginationKey]) || [],
|
||||
) &&
|
||||
((state?.searchResult && state?.searchResult[paginationKey]) || [])
|
||||
.length > 0
|
||||
) {
|
||||
data[paginationKey] = state.searchResult[paginationKey].concat(
|
||||
data[paginationKey],
|
||||
)
|
||||
}
|
||||
emits(
|
||||
'lastIdChange',
|
||||
data.last_id,
|
||||
data.last_group_id,
|
||||
data.last_member_id,
|
||||
)
|
||||
let total = data.count
|
||||
if (props.searchRecordDetail) {
|
||||
total = data.group_record_count
|
||||
}
|
||||
zPaging.value?.completeByTotal([data], total)
|
||||
} else {
|
||||
zPaging.value?.complete([data])
|
||||
}
|
||||
}
|
||||
state.searchResult = data
|
||||
} else {
|
||||
zPaging.value?.complete([])
|
||||
}
|
||||
})
|
||||
|
||||
resp.catch(() => {
|
||||
zPaging.value?.complete([])
|
||||
})
|
||||
}
|
||||
|
||||
//点击取消搜索
|
||||
const cancelSearch = () => {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
})
|
||||
}
|
||||
|
||||
//获取key对应值
|
||||
const getResultKeysValue = (keys) => {
|
||||
let resultKey = ''
|
||||
switch (keys) {
|
||||
case 'user_infos':
|
||||
resultKey = t('index.mine.addressBook')
|
||||
break
|
||||
case 'group_infos':
|
||||
resultKey = t('chat.type.group')
|
||||
break
|
||||
case 'group_member_infos':
|
||||
resultKey = t('chat.type.group')
|
||||
break
|
||||
case 'combinedGroup':
|
||||
resultKey = t('chat.type.group')
|
||||
break
|
||||
case 'general_infos':
|
||||
resultKey = t('chat.type.record')
|
||||
break
|
||||
case 'talk_record_infos':
|
||||
resultKey = t('search.result.relevant') + t('chat.type.record')
|
||||
break
|
||||
default:
|
||||
resultKey = ''
|
||||
}
|
||||
return resultKey
|
||||
}
|
||||
|
||||
//是否还有更多数据
|
||||
const getHasMoreResult = (searchResultKey) => {
|
||||
let has_more_result = ''
|
||||
switch (searchResultKey) {
|
||||
case 'user_infos':
|
||||
if (
|
||||
state.searchResult['user_count'] &&
|
||||
state.searchResult['user_count'] > 3
|
||||
) {
|
||||
has_more_result = t('has_more') + t('index.mine.addressBook')
|
||||
}
|
||||
break
|
||||
case 'group_infos':
|
||||
if (
|
||||
state.searchResult['group_count'] &&
|
||||
state.searchResult['group_count'] > 3
|
||||
) {
|
||||
has_more_result = t('has_more') + t('chat.type.group')
|
||||
}
|
||||
break
|
||||
case 'group_member_infos':
|
||||
if (
|
||||
state.searchResult['group_count'] &&
|
||||
state.searchResult['group_count'] > 3
|
||||
) {
|
||||
has_more_result = t('has_more') + t('chat.type.group')
|
||||
}
|
||||
break
|
||||
case 'combinedGroup':
|
||||
if (
|
||||
state.searchResult['group_count'] &&
|
||||
state.searchResult['group_count'] > 3
|
||||
) {
|
||||
has_more_result = t('has_more') + t('chat.type.group')
|
||||
}
|
||||
break
|
||||
case 'general_infos':
|
||||
break
|
||||
default:
|
||||
}
|
||||
return has_more_result
|
||||
}
|
||||
|
||||
//点击跳转到更多结果页面
|
||||
const toMoreResultPage = (searchResultKey) => {
|
||||
emits('toMoreResultPage', searchResultKey, state.searchText)
|
||||
}
|
||||
|
||||
//点击了搜索结果项
|
||||
const clickSearchItem = (searchResultKey, searchItem) => {
|
||||
emits(
|
||||
'clickSearchItem',
|
||||
state.searchText,
|
||||
searchResultKey,
|
||||
searchItem.talk_type,
|
||||
searchItem.receiver_id,
|
||||
)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.search-list {
|
||||
.searchRoot {
|
||||
padding: 20rpx 48rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
.searchRoot_cancelBtn {
|
||||
line-height: 44rpx;
|
||||
color: $theme-primary;
|
||||
margin: 0 0 0 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
.search-record-detail {
|
||||
padding: 0 50rpx;
|
||||
}
|
||||
.search-result {
|
||||
width: 100%;
|
||||
padding: 0 32rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
.search-result-list {
|
||||
width: 100%;
|
||||
padding: 0 18rpx;
|
||||
|
||||
.search-result-part {
|
||||
margin: 36rpx 0 0;
|
||||
|
||||
.result-title {
|
||||
padding: 0 0 10rpx;
|
||||
span {
|
||||
line-height: 40rpx;
|
||||
color: $theme-hint-text;
|
||||
}
|
||||
}
|
||||
.result-has-more {
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid $theme-border-color;
|
||||
span {
|
||||
color: #191919;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
50
src/pages/search/index.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div class="outer-layer search-page">
|
||||
<div class="root">
|
||||
<searchList
|
||||
:searchResultPageSize="3"
|
||||
:listLimit="true"
|
||||
:apiRequest="ServeSeachQueryAll"
|
||||
@toMoreResultPage="toMoreResultPage"
|
||||
@clickSearchItem="clickSearchItem"
|
||||
></searchList>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import searchList from './components/searchList.vue'
|
||||
import { ServeSeachQueryAll } from '@/api/search/index'
|
||||
|
||||
//点击跳转到更多结果页面
|
||||
const toMoreResultPage = (searchResultKey, searchText) => {
|
||||
uni.navigateTo({
|
||||
url:
|
||||
'/pages/search/moreResult/moreResult?searchResultKey=' +
|
||||
searchResultKey +
|
||||
'&searchText=' +
|
||||
searchText,
|
||||
})
|
||||
}
|
||||
|
||||
//点击了搜索结果项
|
||||
const clickSearchItem = (
|
||||
searchText,
|
||||
searchResultKey,
|
||||
talk_type,
|
||||
receiver_id,
|
||||
) => {
|
||||
console.log(searchResultKey)
|
||||
if (searchResultKey === 'general_infos') {
|
||||
uni.navigateTo({
|
||||
url:
|
||||
'/pages/search/moreResult/moreResultDetail?searchText=' +
|
||||
searchText +
|
||||
'&talk_type=' +
|
||||
talk_type +
|
||||
'&receiver_id=' +
|
||||
receiver_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss"></style>
|
97
src/pages/search/moreResult/moreResult.vue
Normal file
@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="outer-layer search-page">
|
||||
<div class="root">
|
||||
<searchList
|
||||
:searchResultPageSize="10"
|
||||
:listLimit="false"
|
||||
:apiRequest="state.apiRequest"
|
||||
:apiParams="state.apiParams"
|
||||
:searchText="state.searchText"
|
||||
:isPagination="true"
|
||||
@lastIdChange="lastIdChange"
|
||||
@clickSearchItem="clickSearchItem"
|
||||
></searchList>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import searchList from '../components/searchList.vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import {
|
||||
ServeQueryUser,
|
||||
ServeQueryGroup,
|
||||
ServeTalkRecord,
|
||||
} from '@/api/search/index'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const state = reactive({
|
||||
apiRequest: Function,
|
||||
apiParams: String,
|
||||
searchText: String,
|
||||
searchResultKey: String,
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
if (options.searchResultKey) {
|
||||
state.searchResultKey = options.searchResultKey
|
||||
if (options.searchResultKey === 'user_infos') {
|
||||
state.apiParams = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
last_id: 0, //最后一条用户id
|
||||
}),
|
||||
)
|
||||
state.apiRequest = ServeQueryUser
|
||||
} else if (options.searchResultKey === 'combinedGroup') {
|
||||
state.apiParams = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
last_group_id: 0, //最后一条群id
|
||||
last_member_id: 0, //最后一条用户id
|
||||
}),
|
||||
)
|
||||
state.apiRequest = ServeQueryGroup
|
||||
} else if (options.searchResultKey === 'general_infos') {
|
||||
state.apiParams = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
talk_type: 0, //1私聊2群聊
|
||||
receiver_id: 0, //查详情的时候需传入
|
||||
last_group_id: 0, //最后一条群id
|
||||
last_member_id: 0, //最后一条用户id
|
||||
}),
|
||||
)
|
||||
state.apiRequest = ServeTalkRecord
|
||||
}
|
||||
}
|
||||
if (options.searchText) {
|
||||
state.searchText = options.searchText
|
||||
}
|
||||
})
|
||||
|
||||
//分页查询时,最后一条id变化
|
||||
const lastIdChange = (last_id, last_group_id, last_member_id) => {
|
||||
let idChanges = {
|
||||
last_id,
|
||||
last_group_id,
|
||||
last_member_id,
|
||||
}
|
||||
state.apiParams = encodeURIComponent(
|
||||
JSON.stringify(
|
||||
Object.assign(
|
||||
{},
|
||||
JSON.parse(decodeURIComponent(state.apiParams)),
|
||||
idChanges,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//点击了搜索结果项
|
||||
const clickSearchItem = (searchText) => {
|
||||
if (state.searchResultKey === 'general_infos') {
|
||||
uni.navigateTo({
|
||||
url: '/pages/search/moreResult/moreResultDetail?searchText=' + searchText,
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss"></style>
|
71
src/pages/search/moreResult/moreResultDetail.vue
Normal file
@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div class="outer-layer search-page">
|
||||
<div class="root">
|
||||
<searchList
|
||||
:searchResultPageSize="10"
|
||||
:listLimit="false"
|
||||
:apiRequest="ServeTalkRecord"
|
||||
:apiParams="state.apiParams"
|
||||
:searchText="state.searchText"
|
||||
:isPagination="true"
|
||||
:searchRecordDetail="true"
|
||||
@lastIdChange="lastIdChange"
|
||||
></searchList>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import searchList from '../components/searchList.vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ServeTalkRecord } from '@/api/search/index'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const state = reactive({
|
||||
apiParams: String,
|
||||
searchText: String,
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
let talk_type = 0
|
||||
if (options.talk_type) {
|
||||
talk_type = Number(options.talk_type)
|
||||
}
|
||||
let receiver_id = 0
|
||||
if (options.receiver_id) {
|
||||
receiver_id = Number(options.receiver_id)
|
||||
}
|
||||
state.apiParams = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
talk_type: talk_type, //1私聊2群聊
|
||||
receiver_id: receiver_id, //查详情的时候需传入
|
||||
last_group_id: 0, //最后一条群id
|
||||
last_member_id: 0, //最后一条用户id
|
||||
}),
|
||||
)
|
||||
if (options.searchText) {
|
||||
state.searchText = options.searchText
|
||||
}
|
||||
|
||||
console.log(JSON.parse(decodeURIComponent(state.apiParams)))
|
||||
})
|
||||
|
||||
//分页查询时,最后一条id变化
|
||||
const lastIdChange = (last_id, last_group_id, last_member_id) => {
|
||||
let idChanges = {
|
||||
last_id,
|
||||
last_group_id,
|
||||
last_member_id,
|
||||
}
|
||||
state.apiParams = encodeURIComponent(
|
||||
JSON.stringify(
|
||||
Object.assign(
|
||||
{},
|
||||
JSON.parse(decodeURIComponent(state.apiParams)),
|
||||
idChanges,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss"></style>
|
241
src/pages/search/searchByCondition/index.vue
Normal file
@ -0,0 +1,241 @@
|
||||
<template>
|
||||
<div class="outer-layer search-by-condition-page">
|
||||
<div class="root">
|
||||
<ZPaging ref="zPaging" :show-scrollbar="false">
|
||||
<template #top>
|
||||
<tm-navbar :hideBack="false" hideHome title="" :leftWidth="220">
|
||||
<div class="navBar-title flex flex-col items-center justify-center">
|
||||
<span class="text-[34rpx] font-medium">
|
||||
{{ state.pageTitle }}
|
||||
</span>
|
||||
</div>
|
||||
</tm-navbar>
|
||||
</template>
|
||||
<div v-if="state.condition === 'date'" class="search-by-date">
|
||||
<tm-time-picker
|
||||
:show="state.showMonthPicker"
|
||||
:showDetail="{
|
||||
year: true,
|
||||
month: true,
|
||||
day: false,
|
||||
hour: false,
|
||||
minute: false,
|
||||
second: false,
|
||||
am_pm: false,
|
||||
}"
|
||||
:showSuffix="{
|
||||
year: '',
|
||||
month: '',
|
||||
}"
|
||||
:defaultValue="state.nowDate"
|
||||
format="YYYY年MM月"
|
||||
start=""
|
||||
:end="state.maxDate"
|
||||
@confirm="confirmSelectedMonth"
|
||||
:round="0"
|
||||
:title="$t('search.condition.date_pickerTitle')"
|
||||
>
|
||||
<div class="search-date-picker">
|
||||
<span class="text-[28rpx] font-regular">
|
||||
{{ state.selectedMonth }}
|
||||
</span>
|
||||
<img src="/src/static/image/search/down-pointer.png" />
|
||||
</div>
|
||||
</tm-time-picker>
|
||||
<tm-calendar-view
|
||||
:show="true"
|
||||
:hideTool="true"
|
||||
:hideButton="true"
|
||||
:dateStyle="state.dateStyle"
|
||||
:defaultValue="state.selectedDateArray"
|
||||
v-model="state.selectedDateArray"
|
||||
:disabledDate="state.disabledDateArray"
|
||||
@click="selectDate"
|
||||
model="day"
|
||||
:end="state.maxDate"
|
||||
@getDArray="getDArray"
|
||||
:showDefault="false"
|
||||
></tm-calendar-view>
|
||||
</div>
|
||||
</ZPaging>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import ZPaging from '@/uni_modules/z-paging/components/z-paging/z-paging.vue'
|
||||
import searchList from '../components/searchList.vue'
|
||||
import { parseTime } from '@/utils/datetime'
|
||||
import { onMounted, reactive } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { ServeTalkDate } from '@/api/search/index'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
let nowDay = new Date().setHours(0, 0, 0, 0)
|
||||
|
||||
const state = reactive({
|
||||
receiver_id: '', //目标人id
|
||||
pageTitle: '', //页面标题
|
||||
dateStyle: [], //日期样式
|
||||
nowDate: new Date(nowDay), //当前时间
|
||||
maxDate: new Date(nowDay), //可选择最大时间
|
||||
selectedDateArray: Array(new Date(nowDay)), //选择的月份数组
|
||||
showMonthPicker: false, //是否显示月份选择
|
||||
selectedMonth: new Date(nowDay), //当前选择的月份
|
||||
disabledDateArray: [], //被禁用的日期数组
|
||||
dArray: [], //日历日期数组
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
console.log(options)
|
||||
if (options.receiver_id) {
|
||||
state.receiver_id = Number(options.receiver_id)
|
||||
}
|
||||
if (options.condition) {
|
||||
state.condition = options.condition
|
||||
if (options.condition === 'date') {
|
||||
state.pageTitle = t('search.condition.date')
|
||||
ServeQueryTalkDate(parseTime(state.nowDate, '{y}{m}'))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
state.selectedMonth = parseTime(state.selectedMonth, '{y}年{m}月')
|
||||
state.dateStyle = [
|
||||
{
|
||||
date: state.nowDate, //日期
|
||||
text: false, //浅色背景。
|
||||
color: '#46299D', //主题色.
|
||||
extra: '今天', //额外的内容,在日期下方显示的文本。
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
//查看存在聊天记录的天数
|
||||
const ServeQueryTalkDate = (month) => {
|
||||
let params = {
|
||||
month: month,
|
||||
talk_type: 2, //1私聊2群聊
|
||||
receiver_id: state.receiver_id, //目标人id
|
||||
}
|
||||
const resp = ServeTalkDate(params)
|
||||
console.log(resp)
|
||||
resp.then(({ code, data }) => {
|
||||
console.log(data)
|
||||
if (code == 200) {
|
||||
if (data && data.length > 0) {
|
||||
const formattedData = data.map(
|
||||
(item) =>
|
||||
item.substring(0, 4) +
|
||||
'/' +
|
||||
item.substring(4, 6) +
|
||||
'/' +
|
||||
item.substring(6, 8),
|
||||
)
|
||||
let disabledDateArray = state.dArray.filter(
|
||||
(dIt) => !formattedData.includes(dIt),
|
||||
)
|
||||
disabledDateArray = disabledDateArray.map((item) =>
|
||||
item.replace(/\//g, '-'),
|
||||
)
|
||||
console.log(disabledDateArray)
|
||||
state.disabledDateArray = disabledDateArray
|
||||
} else {
|
||||
state.disabledDateArray = state.dArray
|
||||
}
|
||||
} else {
|
||||
}
|
||||
})
|
||||
|
||||
resp.catch(() => {})
|
||||
}
|
||||
|
||||
//点击选择日期
|
||||
const selectDate = (e) => {
|
||||
if (e == parseTime(state.nowDate, '{y}/{m}/{d}')) {
|
||||
console.log('==今日')
|
||||
state.dateStyle = [
|
||||
{
|
||||
date: state.nowDate, //日期
|
||||
text: false, //浅色背景。
|
||||
color: '#46299D', //主题色.
|
||||
extra: '今天', //额外的内容,在日期下方显示的文本。
|
||||
},
|
||||
]
|
||||
} else {
|
||||
state.dateStyle = [
|
||||
{
|
||||
date: state.nowDate, //日期
|
||||
text: false, //浅色背景。
|
||||
color: '', //主题色.
|
||||
extra: '今天', //额外的内容,在日期下方显示的文本。
|
||||
},
|
||||
{
|
||||
date: new Date(e), //日期
|
||||
text: false, //浅色背景。
|
||||
color: '#46299D', //主题色.
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
//点击确认选择月份
|
||||
const confirmSelectedMonth = (e) => {
|
||||
console.log(e)
|
||||
state.selectedMonth = parseTime(e, '{y}年{m}月')
|
||||
// console.log()
|
||||
let newDate = new Date(e)
|
||||
newDate.setHours(0, 0, 0, 0)
|
||||
newDate.setDate(1)
|
||||
state.selectedDateArray = Array(new Date(newDate))
|
||||
state.dateStyle = [
|
||||
{
|
||||
date: state.nowDate, //日期
|
||||
text: false, //浅色背景。
|
||||
color: '', //主题色.
|
||||
extra: '今天', //额外的内容,在日期下方显示的文本。
|
||||
},
|
||||
]
|
||||
ServeQueryTalkDate(parseTime(e, '{y}{m}'))
|
||||
}
|
||||
|
||||
//获取日历日期数组
|
||||
const getDArray = (dArray) => {
|
||||
state.dArray = dArray
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.search-by-date {
|
||||
.search-date-picker {
|
||||
padding: 20rpx 32rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
span {
|
||||
line-height: 40rpx;
|
||||
color: $theme-hint-text;
|
||||
}
|
||||
img {
|
||||
width: 18rpx;
|
||||
height: 11rpx;
|
||||
margin: 0 0 0 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body::v-deep .text-overflow-1 {
|
||||
color: #666666 !important;
|
||||
line-height: 44rpx !important;
|
||||
font-size: 32rpx !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
body::v-deep .tmicon-times-circle-fill {
|
||||
width: 37rpx;
|
||||
height: 37rpx;
|
||||
}
|
||||
body::v-deep .round-3 {
|
||||
background: linear-gradient(to right, #674bbc, #46299d);
|
||||
}
|
||||
</style>
|
@ -1 +1,4 @@
|
||||
$theme-primary: #46299D;
|
||||
$theme-primary: #46299d;
|
||||
$theme-text: #191919;
|
||||
$theme-hint-text: #999999;
|
||||
$theme-border-color: #f8f8f8;
|
||||
|
3
src/static/css/font.scss
Normal file
@ -0,0 +1,3 @@
|
||||
.font-regular {
|
||||
font-weight: 400;
|
||||
}
|
BIN
src/static/image/chatSettings/add-btn.png
Normal file
After Width: | Height: | Size: 795 B |
BIN
src/static/image/chatSettings/app-icon.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
src/static/image/chatSettings/clear-btn.png
Normal file
After Width: | Height: | Size: 297 B |
BIN
src/static/image/chatSettings/edit-btn.png
Normal file
After Width: | Height: | Size: 519 B |
BIN
src/static/image/chatSettings/pointer.png
Normal file
After Width: | Height: | Size: 370 B |
BIN
src/static/image/chatSettings/recordSearchTypeDate.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
src/static/image/chatSettings/recordSearchTypeFiles.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
src/static/image/chatSettings/recordSearchTypeGroupMembers.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
src/static/image/chatSettings/recordSearchTypeImgAndVideo.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
src/static/image/chatSettings/recordSearchTypeLink.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
src/static/image/search/down-pointer.png
Normal file
After Width: | Height: | Size: 208 B |
BIN
src/static/image/search/search-item-pointer.png
Normal file
After Width: | Height: | Size: 370 B |
BIN
src/static/image/search/search-no-data.png
Normal file
After Width: | Height: | Size: 26 KiB |
@ -7,3 +7,4 @@ export * from '@/store/modules/editor-draft'
|
||||
export * from '@/store/modules/uploads'
|
||||
export * from '@/store/modules/dialogueList'
|
||||
// export * from '@/store/modules/note'
|
||||
export * from '@/store/modules/group'
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
ServeRemoveRecords,
|
||||
ServeRevokeRecords,
|
||||
ServePublishMessage,
|
||||
ServeCollectEmoticon
|
||||
ServeCollectEmoticon,
|
||||
} from '@/api/chat/index'
|
||||
import { ServeGetGroupMembers } from '@/api/group/index'
|
||||
import { useEditorStore } from './editor'
|
||||
@ -22,7 +22,7 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
talk: {
|
||||
username: '',
|
||||
talk_type: 0, // 对话来源[1:私聊;2:群聊]
|
||||
receiver_id: 0
|
||||
receiver_id: 0,
|
||||
},
|
||||
|
||||
// 好友是否正在输入文字
|
||||
@ -55,20 +55,26 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
talk_type: 1, // 对话类型
|
||||
receiver_id: 0, // 接收者ID
|
||||
read_sequence: 0, // 当前已读的最后一条记录
|
||||
records: []
|
||||
}
|
||||
records: [],
|
||||
},
|
||||
},
|
||||
// 转发消息类型
|
||||
forwardType: 1,
|
||||
// 合并转发消息
|
||||
forwardMessages: []
|
||||
forwardMessages: [],
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
// 多选列表
|
||||
selectItems: (state) => state.records.filter((item) => item.isCheck),
|
||||
// 当前对话是否是群聊
|
||||
isGroupTalk: (state) => state.talk.talk_type === 2
|
||||
isGroupTalk: (state) => state.talk.talk_type === 2,
|
||||
//获取被禁言的成员列表
|
||||
getSilenceMember: (state) =>
|
||||
state.members.filter((item) => item.is_mute === 1),
|
||||
//获取群管理员
|
||||
getAdminList: (state) =>
|
||||
state.members.filter((item) => item.leader === 1),
|
||||
},
|
||||
actions: {
|
||||
// 更新在线状态
|
||||
@ -82,7 +88,7 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
this.talk = {
|
||||
username: data.remark || data.name,
|
||||
talk_type: data.talk_type,
|
||||
receiver_id: data.receiver_id
|
||||
receiver_id: data.receiver_id,
|
||||
}
|
||||
|
||||
this.index_name = `${data.talk_type}_${data.receiver_id}`
|
||||
@ -99,7 +105,7 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
// 更新提及列表
|
||||
async updateGroupMembers() {
|
||||
let { code, data } = await ServeGetGroupMembers({
|
||||
group_id: this.talk.receiver_id
|
||||
group_id: this.talk.receiver_id,
|
||||
})
|
||||
|
||||
if (code != 200) return
|
||||
@ -112,7 +118,8 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
leader: o.leader,
|
||||
remark: o.remark,
|
||||
online: false,
|
||||
value: o.nickname
|
||||
value: o.nickname,
|
||||
key: o.key
|
||||
}))
|
||||
},
|
||||
|
||||
@ -191,7 +198,7 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
ServeRemoveRecords({
|
||||
talk_type: this.talk.talk_type,
|
||||
receiver_id: this.talk.receiver_id,
|
||||
msg_ids: msgIds
|
||||
msg_ids: msgIds,
|
||||
}).then((res) => {
|
||||
if (res.code == 200) {
|
||||
this.batchDelDialogueRecord(msgIds)
|
||||
@ -219,9 +226,9 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
type: 'forward',
|
||||
receiver: {
|
||||
talk_type: this.talk.talk_type,
|
||||
receiver_id: this.talk.receiver_id
|
||||
receiver_id: this.talk.receiver_id,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
}
|
||||
|
||||
ServePublishMessage(data).then((res) => {
|
||||
@ -247,6 +254,6 @@ export const useDialogueStore = defineStore('dialogue', {
|
||||
// 设置合并转发消息
|
||||
setForwardMessages(messages) {
|
||||
this.forwardMessages = messages
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
47
src/store/modules/group.js
Normal file
@ -0,0 +1,47 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import {
|
||||
ServeGroupDetail,
|
||||
ServeGetGroupMembers,
|
||||
ServeGetGroupNotices,
|
||||
} from '@/api/group/index'
|
||||
import { useDialogueStore } from '@/store'
|
||||
|
||||
export const useGroupStore = defineStore('group', {
|
||||
state: () => {
|
||||
return {
|
||||
groupInfo: '', //群聊信息
|
||||
memberList: [], //群成员列表
|
||||
groupNotice: [], //群公告
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
//获取群聊信息
|
||||
getGroupInfo: (state) => state.groupInfo,
|
||||
//获取群公告
|
||||
getGroupNotice: (state) => state.groupNotice,
|
||||
},
|
||||
actions: {
|
||||
//获取群聊信息
|
||||
async ServeGroupDetail() {
|
||||
const dialogueStore = useDialogueStore()
|
||||
let { code, data } = await ServeGroupDetail({
|
||||
group_id: dialogueStore.talk.receiver_id,
|
||||
})
|
||||
if (code == 200) {
|
||||
console.log(data)
|
||||
this.groupInfo = data
|
||||
}
|
||||
},
|
||||
//群公告查询
|
||||
async ServeGetGroupNotices() {
|
||||
const dialogueStore = useDialogueStore()
|
||||
let { code, data } = await ServeGetGroupNotices({
|
||||
group_id: dialogueStore.talk.receiver_id,
|
||||
})
|
||||
if (code == 200) {
|
||||
this.groupNotice = data.items
|
||||
} else {
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
@ -18,6 +18,10 @@ export const useTalkStore = defineStore('talk', {
|
||||
topItems: (state) => {
|
||||
return state.items.filter((item) => item.is_top == 1)
|
||||
},
|
||||
// 过滤所有免打扰对话列表
|
||||
disturbItems: (state) => {
|
||||
return state.items.filter((item) => item.is_disturb == 1)
|
||||
},
|
||||
|
||||
// 对话列表
|
||||
talkItems: (state) => {
|
||||
|
@ -1,82 +1,149 @@
|
||||
<template>
|
||||
<view class="flex flex-col relative">
|
||||
<tm-sheet v-if="!props.hideTool" :shadow="0" :round="0" :height="88" :margin="[0, 0]" :padding="[0, 0]" _class="flex flex-col">
|
||||
<view class="flex flex-row flex-row-center-center" style="height: 88rpx">
|
||||
<view @click.stop="prevYear" class="px-16">
|
||||
<tm-icon :userInteractionEnabled="false" :font-size="22" name="tmicon-angle-double-left"></tm-icon>
|
||||
</view>
|
||||
<view @click.stop="prevMonth" class="px-16">
|
||||
<tm-icon :userInteractionEnabled="false" :font-size="22" name="tmicon-angle-left"></tm-icon>
|
||||
</view>
|
||||
<view class="px-12">
|
||||
<tm-text :userInteractionEnabled="false" _class="text-weight-b" :font-size="32" :label="_nowDate"></tm-text>
|
||||
</view>
|
||||
<view @click.stop="nextMonth" class="px-16">
|
||||
<tm-icon :userInteractionEnabled="false" :font-size="22" name="tmicon-angle-right"></tm-icon>
|
||||
</view>
|
||||
<view @click.stop="nextYear" class="px-16">
|
||||
<tm-icon :userInteractionEnabled="false" :font-size="22" name="tmicon-angle-double-right"></tm-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
@click="nowWeekClick"
|
||||
class="absolute t-0 r--6 zIndex-10 round-12 py-4 flex flex-row flex-row-center-center"
|
||||
style="width: 90rpx; height: 88rpx"
|
||||
>
|
||||
<tm-text :userInteractionEnabled="false" color="grey" _class="text-align-center" :font-size="28" :label="props.textUnit[8]"></tm-text>
|
||||
</view>
|
||||
</tm-sheet>
|
||||
<view class="flex flex-row flex-row-center-center py-12" :style="[{ height: '74rpx' }]">
|
||||
<view class="flex-1 flex-center" v-for="(item, index) in weekStr" :key="index">
|
||||
<view style="width: 62rpx" class="flex-center flex-col">
|
||||
<tm-text :font-size="24" :label="item"></tm-text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex flex-col">
|
||||
<view class="flex flex-row flex-row-center-center" :style="[{ height: '94rpx' }]" v-for="(item, index) in _data" :key="index">
|
||||
<view @click="clickWeek(item2)" class="flex-1 flex flex-row flex-row-center-center" v-for="(item2, index2) in item" :key="index2">
|
||||
<tm-sheet
|
||||
:userInteractionEnabled="false"
|
||||
:height="90"
|
||||
:width="90"
|
||||
:shadow="0"
|
||||
:round="24"
|
||||
:border="item2.extra.color && isSelected(item2.dateStr) ? 1 : 0"
|
||||
_class="flex-row"
|
||||
:transprent="item2.extra.color || !isSelected(item2.dateStr)"
|
||||
:color="item2.extra.color ? item2.extra.color : isSelected(item2.dateStr) ? _color : 'white'"
|
||||
:margin="[0, 0]"
|
||||
:padding="[0, 0]"
|
||||
>
|
||||
<view
|
||||
:userInteractionEnabled="false"
|
||||
style="width: 62rpx"
|
||||
:class="[!item2.isNowIn ? 'opacity-6' : '']"
|
||||
class="flex-1 flex-center"
|
||||
>
|
||||
<view style="width: 62rpx" class="flex-center flex-col" :style="[{ opacity: item2.disabled ? '0.3' : '1' }]">
|
||||
<tm-text :font-size="28" :label="item2.date"></tm-text>
|
||||
<tm-text _class="flex-center" v-if="item2.extra.extra" :font-size="22" :label="item2.extra.extra"></tm-text>
|
||||
</view>
|
||||
</view>
|
||||
</tm-sheet>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex flex-col relative">
|
||||
<tm-sheet
|
||||
v-if="!props.hideTool"
|
||||
:shadow="0"
|
||||
:round="0"
|
||||
:height="88"
|
||||
:margin="[0, 0]"
|
||||
:padding="[0, 0]"
|
||||
_class="flex flex-col"
|
||||
>
|
||||
<view class="flex flex-row flex-row-center-center" style="height: 88rpx;">
|
||||
<view @click.stop="prevYear" class="px-16">
|
||||
<tm-icon
|
||||
:userInteractionEnabled="false"
|
||||
:font-size="22"
|
||||
name="tmicon-angle-double-left"
|
||||
></tm-icon>
|
||||
</view>
|
||||
<view @click.stop="prevMonth" class="px-16">
|
||||
<tm-icon
|
||||
:userInteractionEnabled="false"
|
||||
:font-size="22"
|
||||
name="tmicon-angle-left"
|
||||
></tm-icon>
|
||||
</view>
|
||||
<view class="px-12">
|
||||
<tm-text
|
||||
:userInteractionEnabled="false"
|
||||
_class="text-weight-b"
|
||||
:font-size="32"
|
||||
:label="_nowDate"
|
||||
></tm-text>
|
||||
</view>
|
||||
<view @click.stop="nextMonth" class="px-16">
|
||||
<tm-icon
|
||||
:userInteractionEnabled="false"
|
||||
:font-size="22"
|
||||
name="tmicon-angle-right"
|
||||
></tm-icon>
|
||||
</view>
|
||||
<view @click.stop="nextYear" class="px-16">
|
||||
<tm-icon
|
||||
:userInteractionEnabled="false"
|
||||
:font-size="22"
|
||||
name="tmicon-angle-double-right"
|
||||
></tm-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
@click="nowWeekClick"
|
||||
class="absolute t-0 r--6 zIndex-10 round-12 py-4 flex flex-row flex-row-center-center"
|
||||
style="width: 90rpx; height: 88rpx;"
|
||||
>
|
||||
<tm-text
|
||||
:userInteractionEnabled="false"
|
||||
color="grey"
|
||||
_class="text-align-center"
|
||||
:font-size="28"
|
||||
:label="props.textUnit[8]"
|
||||
></tm-text>
|
||||
</view>
|
||||
</tm-sheet>
|
||||
<view
|
||||
class="flex flex-row flex-row-center-center py-12"
|
||||
:style="[{ height: '74rpx' }]"
|
||||
>
|
||||
<view
|
||||
class="flex-1 flex-center"
|
||||
v-for="(item, index) in weekStr"
|
||||
:key="index"
|
||||
>
|
||||
<view style="width: 62rpx;" class="flex-center flex-col">
|
||||
<tm-text :font-size="24" :label="item"></tm-text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex flex-col">
|
||||
<view
|
||||
class="flex flex-row flex-row-center-center"
|
||||
:style="[{ height: '94rpx' }]"
|
||||
v-for="(item, index) in _data"
|
||||
:key="index"
|
||||
>
|
||||
<view
|
||||
@click="clickWeek(item2)"
|
||||
class="flex-1 flex flex-row flex-row-center-center"
|
||||
v-for="(item2, index2) in item"
|
||||
:key="index2"
|
||||
>
|
||||
<tm-sheet
|
||||
:userInteractionEnabled="false"
|
||||
:height="90"
|
||||
:width="90"
|
||||
:shadow="0"
|
||||
:round="24"
|
||||
:border="item2.extra.color && isSelected(item2.dateStr) ? 1 : 0"
|
||||
_class="flex-row"
|
||||
:transprent="item2.extra.color || !isSelected(item2.dateStr)"
|
||||
:color="
|
||||
item2.extra.color
|
||||
? item2.extra.color
|
||||
: isSelected(item2.dateStr)
|
||||
? _color
|
||||
: 'white'
|
||||
"
|
||||
:margin="[0, 0]"
|
||||
:padding="[0, 0]"
|
||||
>
|
||||
<view
|
||||
:userInteractionEnabled="false"
|
||||
style="width: 62rpx;"
|
||||
:class="[!item2.isNowIn ? 'opacity-6' : '']"
|
||||
class="flex-1 flex-center"
|
||||
>
|
||||
<view
|
||||
style="width: 62rpx;"
|
||||
class="flex-center flex-col"
|
||||
:style="[{ opacity: item2.disabled ? '0.3' : '1' }]"
|
||||
>
|
||||
<tm-text :font-size="28" :label="item2.date"></tm-text>
|
||||
<tm-text
|
||||
_class="flex-center"
|
||||
v-if="item2.extra.extra"
|
||||
:font-size="22"
|
||||
:label="item2.extra.extra"
|
||||
></tm-text>
|
||||
</view>
|
||||
</view>
|
||||
</tm-sheet>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<tm-button
|
||||
:followTheme="props.followTheme"
|
||||
v-if="!props.hideButton"
|
||||
:linear="props.linear"
|
||||
:linear-deep="props.linearDeep"
|
||||
:color="props.color"
|
||||
@click="confirm"
|
||||
block
|
||||
:label="_confirmText"
|
||||
:margin="[0, 16]"
|
||||
></tm-button>
|
||||
</view>
|
||||
<tm-button
|
||||
:followTheme="props.followTheme"
|
||||
v-if="!props.hideButton"
|
||||
:linear="props.linear"
|
||||
:linear-deep="props.linearDeep"
|
||||
:color="props.color"
|
||||
@click="confirm"
|
||||
block
|
||||
:label="_confirmText"
|
||||
:margin="[0, 16]"
|
||||
></tm-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -103,88 +170,116 @@ const store = useTmpiniaStore()
|
||||
* click-day 日期被选中时触发,注意禁用的日期不会触发 。
|
||||
* change 当切换年或者月的时候触发。
|
||||
*/
|
||||
const emits = defineEmits(['update:modelValue', 'confirm', 'click-day', 'change'])
|
||||
const emits = defineEmits([
|
||||
'update:modelValue',
|
||||
'confirm',
|
||||
'click-day',
|
||||
'change',
|
||||
'getDArray',
|
||||
])
|
||||
const props = defineProps({
|
||||
followTheme: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//默认显示的日期
|
||||
defaultValue: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => []
|
||||
},
|
||||
//当前的周时间段
|
||||
modelValue: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => []
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: 'primary'
|
||||
},
|
||||
linear: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
linearDeep: {
|
||||
type: String,
|
||||
default: 'light'
|
||||
},
|
||||
//指的是:有效的可选时间,小于此时间,不允许选中。
|
||||
start: {
|
||||
type: [String, Number, Date],
|
||||
default: ''
|
||||
},
|
||||
//指的是:有效的可选时间,大于此时间,不允许选中。
|
||||
end: {
|
||||
type: [String, Number, Date],
|
||||
default: ''
|
||||
},
|
||||
//被禁用的日期数组。如果["2022-1-1","2022-5-1"]
|
||||
//被禁用的日期将无法选中。
|
||||
disabledDate: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => []
|
||||
},
|
||||
//是否允许多选。
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//设定单个日期的样式。
|
||||
dateStyle: {
|
||||
type: Array as PropType<Array<dateItemStyle>>,
|
||||
default: () => []
|
||||
},
|
||||
//当multiple=true时,可以选择的最大日期数量。
|
||||
max: {
|
||||
type: Number,
|
||||
default: 999
|
||||
},
|
||||
//隐藏头部操作栏
|
||||
hideTool: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//隐藏底部确认按钮
|
||||
hideButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
},
|
||||
//周次,本日、本季、本年、本月、本周的文字请按顺序提供文本,方便定义其它语言。
|
||||
textUnit: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: ['周次','一','二','三','四','五','六','日','本日','本周','本月','本季度','本年','月','第${x}季度','年']
|
||||
}
|
||||
followTheme: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
//默认显示的日期
|
||||
defaultValue: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => [],
|
||||
},
|
||||
//当前的周时间段
|
||||
modelValue: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => [],
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: 'primary',
|
||||
},
|
||||
linear: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
linearDeep: {
|
||||
type: String,
|
||||
default: 'light',
|
||||
},
|
||||
//指的是:有效的可选时间,小于此时间,不允许选中。
|
||||
start: {
|
||||
type: [String, Number, Date],
|
||||
default: '',
|
||||
},
|
||||
//指的是:有效的可选时间,大于此时间,不允许选中。
|
||||
end: {
|
||||
type: [String, Number, Date],
|
||||
default: '',
|
||||
},
|
||||
//被禁用的日期数组。如果["2022-1-1","2022-5-1"]
|
||||
//被禁用的日期将无法选中。
|
||||
disabledDate: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => [],
|
||||
},
|
||||
//是否允许多选。
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//设定单个日期的样式。
|
||||
dateStyle: {
|
||||
type: Array as PropType<Array<dateItemStyle>>,
|
||||
default: () => [],
|
||||
},
|
||||
//当multiple=true时,可以选择的最大日期数量。
|
||||
max: {
|
||||
type: Number,
|
||||
default: 999,
|
||||
},
|
||||
//隐藏头部操作栏
|
||||
hideTool: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//隐藏底部确认按钮
|
||||
hideButton: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认',
|
||||
},
|
||||
//周次,本日、本季、本年、本月、本周的文字请按顺序提供文本,方便定义其它语言。
|
||||
textUnit: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: [
|
||||
'周次',
|
||||
'一',
|
||||
'二',
|
||||
'三',
|
||||
'四',
|
||||
'五',
|
||||
'六',
|
||||
'日',
|
||||
'本日',
|
||||
'本周',
|
||||
'本月',
|
||||
'本季度',
|
||||
'本年',
|
||||
'月',
|
||||
'第${x}季度',
|
||||
'年',
|
||||
],
|
||||
},
|
||||
showDefault: {
|
||||
//是否显示被选中的默认样式
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
})
|
||||
const _color = computed(() => {
|
||||
if (props.followTheme && store.tmStore.color) return store.tmStore.color
|
||||
return props.color
|
||||
if (props.followTheme && store.tmStore.color) return store.tmStore.color
|
||||
return props.color
|
||||
})
|
||||
const _confirmText = computed(() => props.confirmText)
|
||||
|
||||
@ -194,7 +289,7 @@ DayJs.extend(isSameOrBefore)
|
||||
DayJs.extend(isBetween)
|
||||
//当前选中的时间数组。
|
||||
const _value = ref(props.defaultValue)
|
||||
const weekStr = props.textUnit.slice(1,8)
|
||||
const weekStr = props.textUnit.slice(1, 8)
|
||||
|
||||
//当前需要展示的年月。
|
||||
const showOpenDate: Ref<dayjs.Dayjs> = ref(setShowopenDate())
|
||||
@ -202,233 +297,251 @@ const showOpenDate: Ref<dayjs.Dayjs> = ref(setShowopenDate())
|
||||
const _data: Ref<Array<Array<monthDayItem>>> = ref([])
|
||||
//可选中开始时间
|
||||
const _start_date = computed(() => {
|
||||
let isv = DayJs(props.start).isValid()
|
||||
return isv ? DayJs(props.start) : DayJs('1980-1-1')
|
||||
let isv = DayJs(props.start).isValid()
|
||||
return isv ? DayJs(props.start) : DayJs('1980-1-1')
|
||||
})
|
||||
//可选中的结束时间
|
||||
const _end_date = computed(() => {
|
||||
let isv = DayJs(props.end).isValid()
|
||||
return isv ? DayJs(props.end) : DayJs('2450-1-1')
|
||||
let isv = DayJs(props.end).isValid()
|
||||
return isv ? DayJs(props.end) : DayJs('2450-1-1')
|
||||
})
|
||||
|
||||
//当前展示的年月日期。
|
||||
const _nowDate = computed(() => {
|
||||
return showOpenDate.value.format('YYYY-MM')
|
||||
return showOpenDate.value.format('YYYY-MM')
|
||||
})
|
||||
_data.value = getWeekOfMonthArray()
|
||||
|
||||
watch(
|
||||
[() => props.modelValue, () => props.dateStyle, () => props.disabledDate, () => props.start, () => props.end],
|
||||
() => {
|
||||
_value.value = props.modelValue
|
||||
showOpenDate.value = setShowopenDate()
|
||||
_data.value = getWeekOfMonthArray()
|
||||
},
|
||||
{ deep: true }
|
||||
[
|
||||
() => props.modelValue,
|
||||
() => props.dateStyle,
|
||||
() => props.disabledDate,
|
||||
() => props.start,
|
||||
() => props.end,
|
||||
],
|
||||
() => {
|
||||
_value.value = props.modelValue
|
||||
showOpenDate.value = setShowopenDate()
|
||||
_data.value = getWeekOfMonthArray(true)
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
//设置当前需要展示的月份。
|
||||
function setShowopenDate() {
|
||||
//从当前选中的第一个日期开始。如果没有就显示当前本地时间的月。
|
||||
//从当前选中的第一个日期开始。如果没有就显示当前本地时间的月。
|
||||
|
||||
if (_value.value.length == 0) {
|
||||
return DayJs()
|
||||
}
|
||||
let n = _value.value[0] || DayJs()
|
||||
n = typeof n == 'undefined' || n == null ? DayJs() : n
|
||||
return DayJs(n)
|
||||
if (_value.value.length == 0) {
|
||||
return DayJs()
|
||||
}
|
||||
let n = _value.value[0] || DayJs()
|
||||
n = typeof n == 'undefined' || n == null ? DayJs() : n
|
||||
return DayJs(n)
|
||||
}
|
||||
|
||||
function nowWeekClick() {
|
||||
if (isDisabledDate(DayJs())) {
|
||||
uni.showToast({ title: '无法选中', icon: 'none' })
|
||||
return
|
||||
}
|
||||
selected(DayJs().format('YYYY/MM/DD'))
|
||||
showOpenDate.value = DayJs()
|
||||
_data.value = getWeekOfMonthArray()
|
||||
emits('click-day', DayJs().format('YYYY/MM/DD'))
|
||||
if (isDisabledDate(DayJs())) {
|
||||
uni.showToast({ title: '无法选中', icon: 'none' })
|
||||
return
|
||||
}
|
||||
selected(DayJs().format('YYYY/MM/DD'))
|
||||
showOpenDate.value = DayJs()
|
||||
_data.value = getWeekOfMonthArray()
|
||||
emits('click-day', DayJs().format('YYYY/MM/DD'))
|
||||
}
|
||||
function clickWeek(wk: monthDayItem) {
|
||||
if (wk.disabled) {
|
||||
uni.showToast({ title: '无法选中', icon: 'none' })
|
||||
return
|
||||
}
|
||||
selected(wk.dateStr)
|
||||
emits('click-day', wk.dateStr)
|
||||
if (wk.disabled) {
|
||||
if (props.showDefault) {
|
||||
uni.showToast({ title: '无法选中', icon: 'none' })
|
||||
}
|
||||
return
|
||||
}
|
||||
selected(wk.dateStr)
|
||||
emits('click-day', wk.dateStr)
|
||||
}
|
||||
//选中日期。相同需要减去。重复需要去除。
|
||||
function selected(item: string | dayjs.Dayjs | number) {
|
||||
let fr = _value.value.filter((el) => DayJs(el).isSame(item))
|
||||
if (!props.multiple) {
|
||||
_value.value = [DayJs(item).format('YYYY/MM/DD')]
|
||||
return
|
||||
}
|
||||
let fr = _value.value.filter((el) => DayJs(el).isSame(item))
|
||||
if (!props.multiple) {
|
||||
_value.value = [DayJs(item).format('YYYY/MM/DD')]
|
||||
return
|
||||
}
|
||||
|
||||
if (fr.length > 0) {
|
||||
_value.value = _value.value.filter((el) => !DayJs(el).isSame(item))
|
||||
} else {
|
||||
if (_value.value.length >= props.max) {
|
||||
uni.showToast({ title: '只可选择' + props.max + '天', icon: 'none' })
|
||||
return
|
||||
}
|
||||
_value.value.push(DayJs(item).format('YYYY/MM/DD'))
|
||||
}
|
||||
if (fr.length > 0) {
|
||||
_value.value = _value.value.filter((el) => !DayJs(el).isSame(item))
|
||||
} else {
|
||||
if (_value.value.length >= props.max) {
|
||||
uni.showToast({ title: '只可选择' + props.max + '天', icon: 'none' })
|
||||
return
|
||||
}
|
||||
_value.value.push(DayJs(item).format('YYYY/MM/DD'))
|
||||
}
|
||||
}
|
||||
function nextYear() {
|
||||
showOpenDate.value = showOpenDate.value.add(1, 'year')
|
||||
let dys = getWeekOfMonthArray()
|
||||
emits('change', showOpenDate.value.format('YYYY/MM/DD'))
|
||||
nextTick(() => {
|
||||
_data.value = [...dys]
|
||||
})
|
||||
showOpenDate.value = showOpenDate.value.add(1, 'year')
|
||||
let dys = getWeekOfMonthArray()
|
||||
emits('change', showOpenDate.value.format('YYYY/MM/DD'))
|
||||
nextTick(() => {
|
||||
_data.value = [...dys]
|
||||
})
|
||||
}
|
||||
function nextMonth() {
|
||||
showOpenDate.value = showOpenDate.value.add(1, 'month')
|
||||
let dys = getWeekOfMonthArray()
|
||||
emits('change', showOpenDate.value.format('YYYY/MM/DD'))
|
||||
nextTick(() => {
|
||||
_data.value = [...dys]
|
||||
})
|
||||
showOpenDate.value = showOpenDate.value.add(1, 'month')
|
||||
let dys = getWeekOfMonthArray()
|
||||
emits('change', showOpenDate.value.format('YYYY/MM/DD'))
|
||||
nextTick(() => {
|
||||
_data.value = [...dys]
|
||||
})
|
||||
}
|
||||
function prevMonth() {
|
||||
showOpenDate.value = showOpenDate.value.subtract(1, 'month')
|
||||
let dys = getWeekOfMonthArray()
|
||||
emits('change', showOpenDate.value.format('YYYY/MM/DD'))
|
||||
nextTick(() => {
|
||||
_data.value = [...dys]
|
||||
})
|
||||
showOpenDate.value = showOpenDate.value.subtract(1, 'month')
|
||||
let dys = getWeekOfMonthArray()
|
||||
emits('change', showOpenDate.value.format('YYYY/MM/DD'))
|
||||
nextTick(() => {
|
||||
_data.value = [...dys]
|
||||
})
|
||||
}
|
||||
function prevYear() {
|
||||
showOpenDate.value = showOpenDate.value.subtract(1, 'year')
|
||||
let dys = getWeekOfMonthArray()
|
||||
emits('change', showOpenDate.value.format('YYYY/MM/DD'))
|
||||
nextTick(() => {
|
||||
_data.value = [...dys]
|
||||
})
|
||||
showOpenDate.value = showOpenDate.value.subtract(1, 'year')
|
||||
let dys = getWeekOfMonthArray()
|
||||
emits('change', showOpenDate.value.format('YYYY/MM/DD'))
|
||||
nextTick(() => {
|
||||
_data.value = [...dys]
|
||||
})
|
||||
}
|
||||
//设置当前选中的日期范围,参数必须为有效的时间数组。
|
||||
function setDefault(data: Array<String | Number | Date> = []) {
|
||||
_value.value = data.length > 0 ? data : props.modelValue
|
||||
showOpenDate.value = setShowopenDate()
|
||||
_data.value = getWeekOfMonthArray()
|
||||
_value.value = data.length > 0 ? data : props.modelValue
|
||||
showOpenDate.value = setShowopenDate()
|
||||
_data.value = getWeekOfMonthArray()
|
||||
}
|
||||
//获取本月按周分组的时间段。
|
||||
function getWeekOfMonthArray() {
|
||||
let nowMonth: dayjs.Dayjs = showOpenDate.value.date(1)
|
||||
let startStatickDay = nowMonth.startOf('month')
|
||||
let endStatickDay = nowMonth.endOf('month')
|
||||
function getWeekOfMonthArray(needDarray = false) {
|
||||
let nowMonth: dayjs.Dayjs = showOpenDate.value.date(1)
|
||||
let startStatickDay = nowMonth.startOf('month')
|
||||
let endStatickDay = nowMonth.endOf('month')
|
||||
|
||||
///当前月份有多少天。
|
||||
let nowMonthDayNum = nowMonth.daysInMonth()
|
||||
//第一个日期需要补齐1-7天的。
|
||||
let startOfday = startStatickDay.isoWeekday() - 1
|
||||
///当前月份有多少天。
|
||||
let nowMonthDayNum = nowMonth.daysInMonth()
|
||||
//第一个日期需要补齐1-7天的。
|
||||
let startOfday = startStatickDay.isoWeekday() - 1
|
||||
|
||||
startStatickDay = nowMonth.subtract(Math.abs(startOfday), 'day')
|
||||
//最后一个日期也要补齐1-7天。
|
||||
let endOfday = 7 - endStatickDay.isoWeekday()
|
||||
if (endOfday > 0) {
|
||||
endStatickDay = nowMonth.date(nowMonthDayNum).add(Math.abs(endOfday), 'day')
|
||||
}
|
||||
startStatickDay = nowMonth.subtract(Math.abs(startOfday), 'day')
|
||||
//最后一个日期也要补齐1-7天。
|
||||
let endOfday = 7 - endStatickDay.isoWeekday()
|
||||
if (endOfday > 0) {
|
||||
endStatickDay = nowMonth.date(nowMonthDayNum).add(Math.abs(endOfday), 'day')
|
||||
}
|
||||
|
||||
let startd = DayJs(startStatickDay)
|
||||
let arOfmonth: Array<number> = [] //本月的周次。
|
||||
let ar: Array<monthDayItem> = []
|
||||
function setAr() {
|
||||
let dy = props.dateStyle.map((el) => {
|
||||
el.date = DayJs(el.date).format('YYYY/MM/DD')
|
||||
return el
|
||||
})
|
||||
let dyObj = {}
|
||||
dy.forEach((el) => {
|
||||
dyObj[el.date] = el
|
||||
})
|
||||
let dySet = Object.keys(dyObj)
|
||||
while (startd.isSameOrBefore(endStatickDay)) {
|
||||
let idate = startd.format('YYYY/MM/DD')
|
||||
let ext = dySet.includes(idate) ? dyObj[idate] : {}
|
||||
ar.push({
|
||||
dateStr: idate,
|
||||
date: startd.date() < 10 ? '0' + startd.date() : startd.date(),
|
||||
day: startd.isoWeekday(),
|
||||
week: startd.isoWeek(),
|
||||
isNowIn: isInNowMonth(nowMonth, startd),
|
||||
disabled: isDisabledDate(startd),
|
||||
extra: {
|
||||
date: idate,
|
||||
text: false,
|
||||
color: '',
|
||||
extra: '',
|
||||
...ext
|
||||
}
|
||||
})
|
||||
arOfmonth.push(startd.isoWeek())
|
||||
startd = startd.add(1, 'day')
|
||||
}
|
||||
}
|
||||
setAr()
|
||||
// 再检查当前展示时段内有没有满足6*7 42天没有也要补上剩余的天数。
|
||||
if (ar.length < 42) {
|
||||
let chaJi = 42 - ar.length
|
||||
endStatickDay = endStatickDay.add(chaJi, 'day')
|
||||
setAr()
|
||||
}
|
||||
let startd = DayJs(startStatickDay)
|
||||
let arOfmonth: Array<number> = [] //本月的周次。
|
||||
let ar: Array<monthDayItem> = []
|
||||
function setAr() {
|
||||
let dy = props.dateStyle.map((el) => {
|
||||
el.date = DayJs(el.date).format('YYYY/MM/DD')
|
||||
return el
|
||||
})
|
||||
let dyObj = {}
|
||||
dy.forEach((el) => {
|
||||
dyObj[el.date] = el
|
||||
})
|
||||
let dySet = Object.keys(dyObj)
|
||||
while (startd.isSameOrBefore(endStatickDay)) {
|
||||
let idate = startd.format('YYYY/MM/DD')
|
||||
let ext = dySet.includes(idate) ? dyObj[idate] : {}
|
||||
ar.push({
|
||||
dateStr: idate,
|
||||
date: startd.date() < 10 ? '0' + startd.date() : startd.date(),
|
||||
day: startd.isoWeekday(),
|
||||
week: startd.isoWeek(),
|
||||
isNowIn: isInNowMonth(nowMonth, startd),
|
||||
disabled: isDisabledDate(startd),
|
||||
extra: {
|
||||
date: idate,
|
||||
text: false,
|
||||
color: '',
|
||||
extra: '',
|
||||
...ext,
|
||||
},
|
||||
})
|
||||
arOfmonth.push(startd.isoWeek())
|
||||
startd = startd.add(1, 'day')
|
||||
}
|
||||
}
|
||||
setAr()
|
||||
// 再检查当前展示时段内有没有满足6*7 42天没有也要补上剩余的天数。
|
||||
if (ar.length < 42) {
|
||||
let chaJi = 42 - ar.length
|
||||
endStatickDay = endStatickDay.add(chaJi, 'day')
|
||||
setAr()
|
||||
}
|
||||
|
||||
arOfmonth = [...new Set(arOfmonth)]
|
||||
let dArray: Array<Array<monthDayItem>> = []
|
||||
let index = 0
|
||||
dArray.push([])
|
||||
ar.forEach((el) => {
|
||||
if (el.week == arOfmonth[index]) {
|
||||
dArray[index].push(el)
|
||||
} else {
|
||||
index += 1
|
||||
dArray.push([])
|
||||
dArray[index].push(el)
|
||||
}
|
||||
})
|
||||
return dArray
|
||||
arOfmonth = [...new Set(arOfmonth)]
|
||||
let dArray: Array<Array<monthDayItem>> = []
|
||||
let index = 0
|
||||
dArray.push([])
|
||||
ar.forEach((el) => {
|
||||
if (el.week == arOfmonth[index]) {
|
||||
dArray[index].push(el)
|
||||
} else {
|
||||
index += 1
|
||||
dArray.push([])
|
||||
dArray[index].push(el)
|
||||
}
|
||||
})
|
||||
if (needDarray) {
|
||||
let datesArr: Array<String> = []
|
||||
ar.forEach((it) => {
|
||||
datesArr.push(it.dateStr)
|
||||
})
|
||||
emits('getDArray', datesArr)
|
||||
}
|
||||
return dArray
|
||||
}
|
||||
// 检测now日期是否在某个日期的月份中.
|
||||
function isInNowMonth(date: string | dayjs.Dayjs | number = '', now: string | dayjs.Dayjs | number = '') {
|
||||
let startStatickDay = DayJs(date).startOf('month').format('YYYY/MM/DD')
|
||||
let endStatickDay = DayJs(date).endOf('month').format('YYYY/MM/DD')
|
||||
return DayJs(now).isBetween(startStatickDay, endStatickDay, 'day', '[]')
|
||||
function isInNowMonth(
|
||||
date: string | dayjs.Dayjs | number = '',
|
||||
now: string | dayjs.Dayjs | number = '',
|
||||
) {
|
||||
let startStatickDay = DayJs(date).startOf('month').format('YYYY/MM/DD')
|
||||
let endStatickDay = DayJs(date).endOf('month').format('YYYY/MM/DD')
|
||||
return DayJs(now).isBetween(startStatickDay, endStatickDay, 'day', '[]')
|
||||
}
|
||||
//检测某个日期,是否在禁用中。
|
||||
function isDisabledDate(date: string | dayjs.Dayjs | number = '') {
|
||||
let valdate = DayJs(date)
|
||||
let isds = false
|
||||
isds = !valdate.isBetween(_start_date.value, _end_date.value, 'day', '[]')
|
||||
for (let i = 0; i < props.disabledDate.length; i++) {
|
||||
let item = props.disabledDate[i]
|
||||
if (DayJs(item).isSame(valdate)) {
|
||||
isds = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return isds
|
||||
let valdate = DayJs(date)
|
||||
let isds = false
|
||||
isds = !valdate.isBetween(_start_date.value, _end_date.value, 'day', '[]')
|
||||
for (let i = 0; i < props.disabledDate.length; i++) {
|
||||
let item = props.disabledDate[i]
|
||||
if (DayJs(item).isSame(valdate)) {
|
||||
isds = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return isds
|
||||
}
|
||||
//检测 某个日期是否被选中。
|
||||
function isSelected(date: string | dayjs.Dayjs | number = '') {
|
||||
let fr = _value.value.filter((el) => DayJs(el).isSame(date))
|
||||
let fr = _value.value.filter((el) => DayJs(el).isSame(date))
|
||||
|
||||
return fr.length > 0
|
||||
return fr.length > 0 && props.showDefault
|
||||
}
|
||||
|
||||
function confirm() {
|
||||
let ar = _value.value.map((el) => DayJs(el).format('YYYY/MM/DD'))
|
||||
emits('update:modelValue', ar)
|
||||
emits('confirm', ar)
|
||||
let ar = _value.value.map((el) => DayJs(el).format('YYYY/MM/DD'))
|
||||
emits('update:modelValue', ar)
|
||||
emits('confirm', ar)
|
||||
}
|
||||
|
||||
//对外方法。
|
||||
defineExpose({
|
||||
setDefault: setDefault,
|
||||
nextYear: nextYear,
|
||||
nextMonth: nextMonth,
|
||||
prevYear: prevYear,
|
||||
prevMonth: prevMonth
|
||||
setDefault: setDefault,
|
||||
nextYear: nextYear,
|
||||
nextMonth: nextMonth,
|
||||
prevYear: prevYear,
|
||||
prevMonth: prevMonth,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
@ -1,137 +1,139 @@
|
||||
<template>
|
||||
<tm-sheet :margin="[0, 0]" :padding="[0, 0]">
|
||||
<!-- 按日选择的日期,可单选,多选。 -->
|
||||
<range-day
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="rDay"
|
||||
@confirm="confirm"
|
||||
@click-day="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'rang'"
|
||||
:dateStyle="props.dateStyle"
|
||||
:disabledDate="props.disabledDate"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></range-day>
|
||||
<month-day
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Day"
|
||||
@confirm="confirm"
|
||||
@click-day="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'day'"
|
||||
:dateStyle="props.dateStyle"
|
||||
:disabledDate="props.disabledDate"
|
||||
:max="props.max"
|
||||
:multiple="props.multiple"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></month-day>
|
||||
<!-- 按年选择 -->
|
||||
<year-du
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Year"
|
||||
@confirm="confirm"
|
||||
@click-year="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'year'"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></year-du>
|
||||
<!-- 按月选择 -->
|
||||
<month-year
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Month"
|
||||
@confirm="confirm"
|
||||
@click-month="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'month'"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></month-year>
|
||||
<!-- 按季度选择 -->
|
||||
<month-quarter
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Month"
|
||||
@confirm="confirm"
|
||||
@click-month="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'quarter'"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></month-quarter>
|
||||
<!-- 按周选择时段 -->
|
||||
<week-day
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Week"
|
||||
@confirm="confirm"
|
||||
@click-week="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'week'"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></week-day>
|
||||
</tm-sheet>
|
||||
<tm-sheet :margin="[0, 0]" :padding="[0, 0]">
|
||||
<!-- 按日选择的日期,可单选,多选。 -->
|
||||
<range-day
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="rDay"
|
||||
@confirm="confirm"
|
||||
@click-day="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'rang'"
|
||||
:dateStyle="props.dateStyle"
|
||||
:disabledDate="props.disabledDate"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></range-day>
|
||||
<month-day
|
||||
:showDefault="props.showDefault"
|
||||
@getDArray="getDArray"
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Day"
|
||||
@confirm="confirm"
|
||||
@click-day="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'day'"
|
||||
:dateStyle="props.dateStyle"
|
||||
:disabledDate="props.disabledDate"
|
||||
:max="props.max"
|
||||
:multiple="props.multiple"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></month-day>
|
||||
<!-- 按年选择 -->
|
||||
<year-du
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Year"
|
||||
@confirm="confirm"
|
||||
@click-year="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'year'"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></year-du>
|
||||
<!-- 按月选择 -->
|
||||
<month-year
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Month"
|
||||
@confirm="confirm"
|
||||
@click-month="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'month'"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></month-year>
|
||||
<!-- 按季度选择 -->
|
||||
<month-quarter
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Month"
|
||||
@confirm="confirm"
|
||||
@click-month="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'quarter'"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></month-quarter>
|
||||
<!-- 按周选择时段 -->
|
||||
<week-day
|
||||
:confirmText="_confirmText"
|
||||
:textUnit="_textUnit"
|
||||
:hideButton="props.hideButton"
|
||||
:hideTool="props.hideTool"
|
||||
:followTheme="props.followTheme"
|
||||
ref="Week"
|
||||
@confirm="confirm"
|
||||
@click-week="click"
|
||||
@change="change"
|
||||
@update:model-value="_value = $event"
|
||||
:model-value="_value"
|
||||
:default-value="_value"
|
||||
v-if="_modelType == 'week'"
|
||||
:start="props.start"
|
||||
:end="props.end"
|
||||
:color="props.color"
|
||||
:linear="props.linear"
|
||||
:linearDeep="props.linearDeep"
|
||||
></week-day>
|
||||
</tm-sheet>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@ -139,8 +141,23 @@
|
||||
* 日历(嵌入页面面板)
|
||||
* @description 可以按月,按日,按周,按季度显示
|
||||
*/
|
||||
import { computed, ref, watch, PropType, Ref, getCurrentInstance, nextTick, watchEffect } from 'vue'
|
||||
import { custom_props, computedTheme, computedClass, computedStyle, computedDark } from '../../tool/lib/minxs'
|
||||
import {
|
||||
computed,
|
||||
ref,
|
||||
watch,
|
||||
PropType,
|
||||
Ref,
|
||||
getCurrentInstance,
|
||||
nextTick,
|
||||
watchEffect,
|
||||
} from 'vue'
|
||||
import {
|
||||
custom_props,
|
||||
computedTheme,
|
||||
computedClass,
|
||||
computedStyle,
|
||||
computedDark,
|
||||
} from '../../tool/lib/minxs'
|
||||
import weekDay from './week-day.vue'
|
||||
import monthYear from './month-year.vue'
|
||||
import yearDu from './year-du.vue'
|
||||
@ -149,7 +166,13 @@ import rangeDay from './range-day.vue'
|
||||
import monthQuarter from './month-quarter.vue'
|
||||
import tmSheet from '../tm-sheet/tm-sheet.vue'
|
||||
import * as dayjs from '../../tool/dayjs/esm'
|
||||
import { monthDayItem, dateItemStyle, monthYearItem, weekItem, yearItem } from './interface'
|
||||
import {
|
||||
monthDayItem,
|
||||
dateItemStyle,
|
||||
monthYearItem,
|
||||
weekItem,
|
||||
yearItem,
|
||||
} from './interface'
|
||||
const proxy = getCurrentInstance()?.proxy ?? null
|
||||
const rDay = ref<InstanceType<typeof rangeDay> | null>(null)
|
||||
const Day = ref<InstanceType<typeof monthDay> | null>(null)
|
||||
@ -163,174 +186,209 @@ const Week = ref<InstanceType<typeof weekDay> | null>(null)
|
||||
* click 日期被选中时触发,注意禁用的日期不会触发 。
|
||||
* change 当切换年或者月的时候触发。
|
||||
*/
|
||||
const emits = defineEmits(['update:modelValue', 'update:modelStr', 'confirm', 'click', 'change'])
|
||||
const emits = defineEmits([
|
||||
'update:modelValue',
|
||||
'update:modelStr',
|
||||
'confirm',
|
||||
'click',
|
||||
'change',
|
||||
'getDArray',
|
||||
])
|
||||
|
||||
const props = defineProps({
|
||||
...custom_props,
|
||||
followTheme: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 数组
|
||||
*/
|
||||
defaultValue: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => []
|
||||
},
|
||||
modelValue: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => []
|
||||
},
|
||||
//单向绑定输入展示日期,此字段用来在页面上展示。只向外输出。
|
||||
//功能目的:用来在页面上显示,特别是在input上绑定显示非常方便。
|
||||
//标准数据保存时,请使用modelValue保存,而不是此值。
|
||||
modelStr: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 日期模式
|
||||
* day : 单个日期选择模式(可多选,需要设置multiple=true;
|
||||
* week :按周选择模式。
|
||||
* month :按月选择模式。
|
||||
* year :按年选择模式。
|
||||
* rang :按日期范围选择模式。
|
||||
* quarter :按季度选择模式。
|
||||
*/
|
||||
model: {
|
||||
type: String as PropType<'quarter' | 'day' | 'month' | 'year' | 'rang' | 'week'>,
|
||||
default: 'day'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: 'primary'
|
||||
},
|
||||
linear: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
linearDeep: {
|
||||
type: String,
|
||||
default: 'light'
|
||||
},
|
||||
//指的是:有效的可选时间,小于此时间,不允许选中。
|
||||
start: {
|
||||
type: [String, Number, Date],
|
||||
default: ''
|
||||
},
|
||||
//指的是:有效的可选时间,大于此时间,不允许选中。
|
||||
end: {
|
||||
type: [String, Number, Date],
|
||||
default: ''
|
||||
},
|
||||
...custom_props,
|
||||
followTheme: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
/**
|
||||
* 数组
|
||||
*/
|
||||
defaultValue: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => [],
|
||||
},
|
||||
modelValue: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => [],
|
||||
},
|
||||
//单向绑定输入展示日期,此字段用来在页面上展示。只向外输出。
|
||||
//功能目的:用来在页面上显示,特别是在input上绑定显示非常方便。
|
||||
//标准数据保存时,请使用modelValue保存,而不是此值。
|
||||
modelStr: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**
|
||||
* 日期模式
|
||||
* day : 单个日期选择模式(可多选,需要设置multiple=true;
|
||||
* week :按周选择模式。
|
||||
* month :按月选择模式。
|
||||
* year :按年选择模式。
|
||||
* rang :按日期范围选择模式。
|
||||
* quarter :按季度选择模式。
|
||||
*/
|
||||
model: {
|
||||
type: String as PropType<
|
||||
'quarter' | 'day' | 'month' | 'year' | 'rang' | 'week'
|
||||
>,
|
||||
default: 'day',
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: 'primary',
|
||||
},
|
||||
linear: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
linearDeep: {
|
||||
type: String,
|
||||
default: 'light',
|
||||
},
|
||||
//指的是:有效的可选时间,小于此时间,不允许选中。
|
||||
start: {
|
||||
type: [String, Number, Date],
|
||||
default: '',
|
||||
},
|
||||
//指的是:有效的可选时间,大于此时间,不允许选中。
|
||||
end: {
|
||||
type: [String, Number, Date],
|
||||
default: '',
|
||||
},
|
||||
|
||||
/** 日历组件属性 */
|
||||
/** 日历组件属性 */
|
||||
|
||||
//被禁用的日期数组。如果["2022-1-1","2022-5-1"]
|
||||
//被禁用的日期将无法选中。
|
||||
disabledDate: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => []
|
||||
},
|
||||
//是否允许多选。
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//设定单个日期的样式。
|
||||
dateStyle: {
|
||||
type: Array as PropType<Array<dateItemStyle>>,
|
||||
default: () => []
|
||||
},
|
||||
//当multiple=true时,可以选择的最大日期数量。
|
||||
max: {
|
||||
type: Number,
|
||||
default: 999
|
||||
},
|
||||
/** 日历组件属性结束 */
|
||||
//隐藏底部确认按钮
|
||||
hideButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//隐藏头部操作栏
|
||||
hideTool: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**modelStr的格式化输出选项,不会影响value值,只对输出值有效 */
|
||||
format: {
|
||||
type: String,
|
||||
default: 'YYYY/MM/DD'
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
},
|
||||
//周次,本日、本季、本年、本月、本周的文字请按顺序提供文本,方便定义其它语言。
|
||||
textUnit: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: ['周次','一','二','三','四','五','六','日','本日','本周','本月','本季度','本年','月','第${x}季度','年']
|
||||
}
|
||||
//被禁用的日期数组。如果["2022-1-1","2022-5-1"]
|
||||
//被禁用的日期将无法选中。
|
||||
disabledDate: {
|
||||
type: Array as PropType<Array<String | Number | Date>>,
|
||||
default: () => [],
|
||||
},
|
||||
//是否允许多选。
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//设定单个日期的样式。
|
||||
dateStyle: {
|
||||
type: Array as PropType<Array<dateItemStyle>>,
|
||||
default: () => [],
|
||||
},
|
||||
//当multiple=true时,可以选择的最大日期数量。
|
||||
max: {
|
||||
type: Number,
|
||||
default: 999,
|
||||
},
|
||||
/** 日历组件属性结束 */
|
||||
//隐藏底部确认按钮
|
||||
hideButton: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
//隐藏头部操作栏
|
||||
hideTool: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**modelStr的格式化输出选项,不会影响value值,只对输出值有效 */
|
||||
format: {
|
||||
type: String,
|
||||
default: 'YYYY/MM/DD',
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认',
|
||||
},
|
||||
//周次,本日、本季、本年、本月、本周的文字请按顺序提供文本,方便定义其它语言。
|
||||
textUnit: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: [
|
||||
'周次',
|
||||
'一',
|
||||
'二',
|
||||
'三',
|
||||
'四',
|
||||
'五',
|
||||
'六',
|
||||
'日',
|
||||
'本日',
|
||||
'本周',
|
||||
'本月',
|
||||
'本季度',
|
||||
'本年',
|
||||
'月',
|
||||
'第${x}季度',
|
||||
'年',
|
||||
],
|
||||
},
|
||||
showDefault: {
|
||||
//是否显示被选中的默认样式
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
})
|
||||
const _value = ref(props.defaultValue)
|
||||
const _modelType = computed(() => props.model)
|
||||
const _confirmText = computed(() => props.confirmText)
|
||||
const _textUnit = computed(() => props.textUnit)
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => (_value.value = props.modelValue),
|
||||
{ deep: true }
|
||||
() => props.modelValue,
|
||||
() => (_value.value = props.modelValue),
|
||||
{ deep: true },
|
||||
)
|
||||
watch(
|
||||
_value,
|
||||
() => {
|
||||
let fmar = _value.value.map((el) => dayjs.default(el).format(props.format))
|
||||
let fm = fmar.join('~')
|
||||
emits('update:modelStr', fm)
|
||||
},
|
||||
{ deep: true }
|
||||
_value,
|
||||
() => {
|
||||
let fmar = _value.value.map((el) => dayjs.default(el).format(props.format))
|
||||
let fm = fmar.join('~')
|
||||
emits('update:modelStr', fm)
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
function change(e: Array<string | number>) {
|
||||
emits('change', e)
|
||||
emits('change', e)
|
||||
}
|
||||
function click(e: Array<string | number>) {
|
||||
emits('click', e)
|
||||
emits('click', e)
|
||||
}
|
||||
function confirm(e: Array<string | number>) {
|
||||
emits('confirm', e)
|
||||
emits('update:modelValue', e)
|
||||
emits('confirm', e)
|
||||
emits('update:modelValue', e)
|
||||
}
|
||||
function getRefs() {
|
||||
if (_modelType.value == 'day') return Day.value
|
||||
if (_modelType.value == 'rang') return rDay.value
|
||||
if (_modelType.value == 'week') return Week.value
|
||||
if (_modelType.value == 'month') return Month.value
|
||||
if (_modelType.value == 'year') return Year.value
|
||||
return Day.value
|
||||
if (_modelType.value == 'day') return Day.value
|
||||
if (_modelType.value == 'rang') return rDay.value
|
||||
if (_modelType.value == 'week') return Week.value
|
||||
if (_modelType.value == 'month') return Month.value
|
||||
if (_modelType.value == 'year') return Year.value
|
||||
return Day.value
|
||||
}
|
||||
/**
|
||||
* ref方法。外部如果要即时调用 ,请注意包裹在nextTick中执行。
|
||||
*/
|
||||
|
||||
defineExpose({
|
||||
setDefault: (e: Event) => {
|
||||
nextTick(() => getRefs().setDefault(e))
|
||||
},
|
||||
nextYear: () => {
|
||||
nextTick(() => getRefs().nextYear())
|
||||
},
|
||||
// mont,year模式下,没有此方法
|
||||
nextMonth: () => {
|
||||
nextTick(() => getRefs().nextMonth())
|
||||
},
|
||||
prevYear: () => {
|
||||
nextTick(() => getRefs().prevYear())
|
||||
},
|
||||
// mont,year模式下,没有此方法
|
||||
prevMonth: () => {
|
||||
nextTick(() => getRefs().prevMonth())
|
||||
}
|
||||
setDefault: (e: Event) => {
|
||||
nextTick(() => getRefs().setDefault(e))
|
||||
},
|
||||
nextYear: () => {
|
||||
nextTick(() => getRefs().nextYear())
|
||||
},
|
||||
// mont,year模式下,没有此方法
|
||||
nextMonth: () => {
|
||||
nextTick(() => getRefs().nextMonth())
|
||||
},
|
||||
prevYear: () => {
|
||||
nextTick(() => getRefs().prevYear())
|
||||
},
|
||||
// mont,year模式下,没有此方法
|
||||
prevMonth: () => {
|
||||
nextTick(() => getRefs().prevMonth())
|
||||
},
|
||||
})
|
||||
|
||||
const getDArray = (dArray: Array<String>) => {
|
||||
emits('getDArray', dArray)
|
||||
}
|
||||
</script>
|
||||
|
@ -123,7 +123,8 @@ const props = defineProps({
|
||||
day: true,
|
||||
hour: false,
|
||||
minute: false,
|
||||
second: false
|
||||
second: false,
|
||||
am_pm: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -5,6 +5,7 @@ export interface showDetail {
|
||||
hour: boolean,
|
||||
minute: boolean,
|
||||
second: boolean,
|
||||
am_pm: boolean
|
||||
}
|
||||
export enum timeDetailType {
|
||||
year = "year",
|
||||
@ -25,4 +26,4 @@ export interface timeArrayType {
|
||||
hour: Array<number>,
|
||||
minute: Array<number>,
|
||||
second: Array<number>,
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
<template>
|
||||
<view class="flex relative flex-col" :style="{ height: props.height + 'rpx' }">
|
||||
<view style="display: flex">
|
||||
<view
|
||||
class="flex relative flex-col"
|
||||
:style="{ height: props.height + 'rpx' }"
|
||||
>
|
||||
<view style="display: flex;">
|
||||
<picker-view
|
||||
v-if="show"
|
||||
:value="colIndex"
|
||||
@change="colchange"
|
||||
:style="{ height: props.height + 'rpx',width:' 100%' }"
|
||||
:style="{ height: props.height + 'rpx', width: ' 100%' }"
|
||||
:mask-style="maskStyle"
|
||||
:immediateChange="props.immediateChange"
|
||||
indicator-style="height:50px"
|
||||
@ -16,7 +19,6 @@
|
||||
:key="index"
|
||||
class="flex itemcel flex-row flex-row-center-center"
|
||||
:class="[colIndex[0] == index ? '' : 'UnitemSelected']"
|
||||
|
||||
>
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<TmText
|
||||
@ -26,9 +28,10 @@
|
||||
></TmText>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<text :style="{color:store.tmStore.dark?'white':'black'}">{{item + showSuffix['year']}}</text>
|
||||
<text :style="{ color: store.tmStore.dark ? 'white' : 'black' }">
|
||||
{{ item + showSuffix['year'] }}
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column v-if="showCol.month">
|
||||
@ -38,7 +41,6 @@
|
||||
class="flex itemcel flex-row flex-row-center-center"
|
||||
:class="[colIndex[1] == index ? '' : 'UnitemSelected']"
|
||||
>
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<TmText
|
||||
:font-size="30"
|
||||
@ -47,9 +49,10 @@
|
||||
></TmText>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<text :style="{color:store.tmStore.dark?'white':'black'}">{{item + 1 + showSuffix['month']}}</text>
|
||||
<text :style="{ color: store.tmStore.dark ? 'white' : 'black' }">
|
||||
{{ item + 1 + showSuffix['month'] }}
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column v-if="showCol.day">
|
||||
@ -59,7 +62,6 @@
|
||||
class="flex itemcel flex-row flex-row-center-center"
|
||||
:class="[colIndex[2] == index ? '' : 'UnitemSelected']"
|
||||
>
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<TmText
|
||||
:font-size="30"
|
||||
@ -68,7 +70,9 @@
|
||||
></TmText>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<text :style="{color:store.tmStore.dark?'white':'black'}">{{item + showSuffix['date']}}</text>
|
||||
<text :style="{ color: store.tmStore.dark ? 'white' : 'black' }">
|
||||
{{ item + showSuffix['date'] }}
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</picker-view-column>
|
||||
@ -79,7 +83,6 @@
|
||||
class="flex itemcel flex-row flex-row-center-center"
|
||||
:class="[colIndex[3] == index ? '' : 'UnitemSelected']"
|
||||
>
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<TmText
|
||||
:font-size="30"
|
||||
@ -88,7 +91,9 @@
|
||||
></TmText>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<text :style="{color:store.tmStore.dark?'white':'black'}">{{item + showSuffix['hour']}}</text>
|
||||
<text :style="{ color: store.tmStore.dark ? 'white' : 'black' }">
|
||||
{{ item + showSuffix['hour'] }}
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</picker-view-column>
|
||||
@ -99,7 +104,6 @@
|
||||
class="flex itemcel flex-row flex-row-center-center"
|
||||
:class="[colIndex[4] == index ? '' : 'UnitemSelected']"
|
||||
>
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<TmText
|
||||
:font-size="30"
|
||||
@ -108,7 +112,9 @@
|
||||
></TmText>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<text :style="{color:store.tmStore.dark?'white':'black'}">{{item + showSuffix['minute']}}</text>
|
||||
<text :style="{ color: store.tmStore.dark ? 'white' : 'black' }">
|
||||
{{ item + showSuffix['minute'] }}
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</picker-view-column>
|
||||
@ -119,7 +125,6 @@
|
||||
class="flex itemcel flex-row flex-row-center-center"
|
||||
:class="[colIndex[5] == index ? '' : 'UnitemSelected']"
|
||||
>
|
||||
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<TmText
|
||||
:font-size="30"
|
||||
@ -128,7 +133,9 @@
|
||||
></TmText>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<text :style="{color:store.tmStore.dark?'white':'black'}">{{item + showSuffix['second']}}</text>
|
||||
<text :style="{ color: store.tmStore.dark ? 'white' : 'black' }">
|
||||
{{ item + showSuffix['second'] }}
|
||||
</text>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</picker-view-column>
|
||||
@ -136,19 +143,24 @@
|
||||
<picker-view
|
||||
:value="ampmIndex"
|
||||
@change="change1"
|
||||
:style="{ height: props.height + 'rpx',width: `${100/(trueCount+1)}%` }"
|
||||
:style="{
|
||||
height: props.height + 'rpx',
|
||||
width: `${100 / (trueCount + 1)}%`,
|
||||
}"
|
||||
:mask-style="maskStyle"
|
||||
:immediateChange="props.immediateChange"
|
||||
indicator-style="height:50px"
|
||||
v-if="showCol.am_pm"
|
||||
>
|
||||
<picker-view-column>
|
||||
<picker-view-column v-if="showCol.am_pm">
|
||||
<view
|
||||
v-for="(item, index) in ['上午','下午']"
|
||||
v-for="(item, index) in ['上午', '下午']"
|
||||
:key="index"
|
||||
class="flex itemcel flex-row flex-row-center-center"
|
||||
>
|
||||
|
||||
<text :style="{color:store.tmStore.dark?'white':'black'}">{{item}}</text>
|
||||
<text :style="{ color: store.tmStore.dark ? 'white' : 'black' }">
|
||||
{{ item }}
|
||||
</text>
|
||||
</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
@ -177,7 +189,7 @@
|
||||
* 时间选择
|
||||
* @description 嵌入在页面的时间选择器。
|
||||
*/
|
||||
import { useTmpiniaStore } from "../../tool/lib/tmpinia";
|
||||
import { useTmpiniaStore } from '../../tool/lib/tmpinia'
|
||||
import {
|
||||
computed,
|
||||
PropType,
|
||||
@ -189,44 +201,44 @@ import {
|
||||
watch,
|
||||
onUpdated,
|
||||
Ref,
|
||||
} from "vue";
|
||||
import { showDetail, coltimeData, timeDetailType } from "./interface";
|
||||
import * as dayjs from "../../tool/dayjs/esm";
|
||||
import { propsOpts } from "./props";
|
||||
} from 'vue'
|
||||
import { showDetail, coltimeData, timeDetailType } from './interface'
|
||||
import * as dayjs from '../../tool/dayjs/esm'
|
||||
import { propsOpts } from './props'
|
||||
import {
|
||||
rangeTimeArray,
|
||||
getNowbyIndex,
|
||||
getIndexNowbydate,
|
||||
checkNowDateisBetween,
|
||||
} from "./time";
|
||||
import TmText from "../tm-text/tm-text.vue";
|
||||
import TmIcon from "../tm-icon/tm-icon.vue";
|
||||
} from './time'
|
||||
import TmText from '../tm-text/tm-text.vue'
|
||||
import TmIcon from '../tm-icon/tm-icon.vue'
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
const dom = uni.requireNativePlugin("dom");
|
||||
const dom = uni.requireNativePlugin('dom')
|
||||
// #endif
|
||||
const proxy = getCurrentInstance()?.proxy ?? null;
|
||||
const store = useTmpiniaStore();
|
||||
const emits = defineEmits(["update:modelValue", "update:modelStr", "change"]);
|
||||
const tmTimeViewName = "tmTimeViewName";
|
||||
const DayJs = dayjs.default;
|
||||
const props = defineProps({ ...propsOpts });
|
||||
const proxy = getCurrentInstance()?.proxy ?? null
|
||||
const store = useTmpiniaStore()
|
||||
const emits = defineEmits(['update:modelValue', 'update:modelStr', 'change'])
|
||||
const tmTimeViewName = 'tmTimeViewName'
|
||||
const DayJs = dayjs.default
|
||||
const props = defineProps({ ...propsOpts })
|
||||
const _nowtime = ref(
|
||||
DayJs(checkNowDateisBetween(props.defaultValue, props.start, props.end))
|
||||
);
|
||||
const _nowtimeValue = computed(() => _nowtime.value.format());
|
||||
DayJs(checkNowDateisBetween(props.defaultValue, props.start, props.end)),
|
||||
)
|
||||
const _nowtimeValue = computed(() => _nowtime.value.format())
|
||||
|
||||
const show = ref(true);
|
||||
const show = ref(true)
|
||||
|
||||
const _startTime = computed(() => {
|
||||
return DayJs(props.start).isValid()
|
||||
? DayJs(props.start).format()
|
||||
: DayJs().subtract(3, "year").format();
|
||||
});
|
||||
: DayJs().subtract(3, 'year').format()
|
||||
})
|
||||
const _endTime = computed(() => {
|
||||
return DayJs(props.end).isValid()
|
||||
? DayJs(props.end).format()
|
||||
: DayJs().add(1, "year").format();
|
||||
});
|
||||
: DayJs().add(1, 'year').format()
|
||||
})
|
||||
const showCol = computed<showDetail>(() => {
|
||||
return {
|
||||
year: props.showDetail?.year ?? true,
|
||||
@ -235,24 +247,25 @@ const showCol = computed<showDetail>(() => {
|
||||
hour: props.showDetail?.hour ?? false,
|
||||
minute: props.showDetail?.minute ?? false,
|
||||
second: props.showDetail?.second ?? false,
|
||||
};
|
||||
});
|
||||
am_pm: props.showDetail?.am_pm ?? true,
|
||||
}
|
||||
})
|
||||
const trueCount = computed(() => {
|
||||
return Object.values(showCol.value).filter(value => value === true).length;
|
||||
});
|
||||
return Object.values(showCol.value).filter((value) => value === true).length
|
||||
})
|
||||
const showSuffix = computed(() => {
|
||||
return {
|
||||
year: props.showSuffix?.year ?? "年",
|
||||
month: props.showSuffix?.month ?? "月",
|
||||
hour: props.showSuffix?.hour ?? "时",
|
||||
minute: props.showSuffix?.minute ?? "分",
|
||||
second: props.showSuffix?.second ?? "秒",
|
||||
date: props.showSuffix?.day ?? "日",
|
||||
};
|
||||
});
|
||||
const isDark = computed(() => store.tmStore.dark);
|
||||
let colIndex: Ref<Array<number>> = ref([0, 0, 0, 0, 0, 0]);
|
||||
let ampmIndex: Ref<Array<number>> = ref([0]);
|
||||
year: props.showSuffix?.year ?? '年',
|
||||
month: props.showSuffix?.month ?? '月',
|
||||
hour: props.showSuffix?.hour ?? '时',
|
||||
minute: props.showSuffix?.minute ?? '分',
|
||||
second: props.showSuffix?.second ?? '秒',
|
||||
date: props.showSuffix?.day ?? '日',
|
||||
}
|
||||
})
|
||||
const isDark = computed(() => store.tmStore.dark)
|
||||
let colIndex: Ref<Array<number>> = ref([0, 0, 0, 0, 0, 0])
|
||||
let ampmIndex: Ref<Array<number>> = ref([0])
|
||||
const _col = ref({
|
||||
year: [] as Array<number>,
|
||||
month: [] as Array<number>,
|
||||
@ -260,129 +273,144 @@ const _col = ref({
|
||||
hour: [] as Array<number>,
|
||||
minute: [] as Array<number>,
|
||||
second: [] as Array<number>,
|
||||
});
|
||||
})
|
||||
|
||||
let timid = NaN;
|
||||
const maskWidth = ref(0);
|
||||
let timid = NaN
|
||||
const maskWidth = ref(0)
|
||||
const maskHeight = computed(() => {
|
||||
return (uni.upx2px(props.height) - 50) / 2;
|
||||
});
|
||||
return (uni.upx2px(props.height) - 50) / 2
|
||||
})
|
||||
const maskStyle = computed(() => {
|
||||
let str_white =
|
||||
"background-image:linear-gradient(rgba(255,255,255,0.95),rgba(255,255,255,0.6)),linear-gradient(rgba(255,255,255,0.6),rgba(255,255,255,0.95))";
|
||||
'background-image:linear-gradient(rgba(255,255,255,0.95),rgba(255,255,255,0.6)),linear-gradient(rgba(255,255,255,0.6),rgba(255,255,255,0.95))'
|
||||
let str_black =
|
||||
"background-image:linear-gradient(rgba(17, 17, 17, 1.0),rgba(106, 106, 106, 0.2)),linear-gradient(rgba(106, 106, 106, 0.2),rgba(17, 17, 17, 1.0))";
|
||||
'background-image:linear-gradient(rgba(17, 17, 17, 1.0),rgba(106, 106, 106, 0.2)),linear-gradient(rgba(106, 106, 106, 0.2),rgba(17, 17, 17, 1.0))'
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
str_black =
|
||||
"background-image: linear-gradient(to bottom,rgba(30, 30, 30, 0.9),rgba(104, 104, 104, 0.6))";
|
||||
'background-image: linear-gradient(to bottom,rgba(30, 30, 30, 0.9),rgba(104, 104, 104, 0.6))'
|
||||
// #endif
|
||||
if (!isDark.value) {
|
||||
return str_white;
|
||||
return str_white
|
||||
}
|
||||
return str_black;
|
||||
});
|
||||
return str_black
|
||||
})
|
||||
_col.value = rangeTimeArray(
|
||||
_nowtimeValue.value,
|
||||
_startTime.value,
|
||||
_endTime.value,
|
||||
showCol.value
|
||||
);
|
||||
function change1(data){
|
||||
console.log('data',data)
|
||||
showCol.value,
|
||||
)
|
||||
function change1(data) {
|
||||
console.log('data', data)
|
||||
}
|
||||
function colchange(e: any) {
|
||||
|
||||
let changedate = getNowbyIndex(_col.value, e.detail.value, showCol.value, _startTime.value,_endTime.value);
|
||||
let testDate = checkNowDateisBetween(changedate, _startTime.value,_endTime.value)
|
||||
|
||||
|
||||
let changedate = getNowbyIndex(
|
||||
_col.value,
|
||||
e.detail.value,
|
||||
showCol.value,
|
||||
_startTime.value,
|
||||
_endTime.value,
|
||||
)
|
||||
let testDate = checkNowDateisBetween(
|
||||
changedate,
|
||||
_startTime.value,
|
||||
_endTime.value,
|
||||
)
|
||||
|
||||
let testRang = rangeTimeArray(
|
||||
testDate,
|
||||
_startTime.value,
|
||||
_endTime.value,
|
||||
showCol.value
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
_nowtime.value = DayJs(testDate);
|
||||
colIndex.value = getIndexNowbydate(testRang, _nowtime.value, showCol.value);
|
||||
emits("update:modelValue", _nowtime.value.format("YYYY/MM/DD HH:mm:ss"));
|
||||
emits("update:modelStr", _nowtime.value.format(props.format));
|
||||
emits("change", _nowtime.value.format(props.format));
|
||||
|
||||
_col.value= testRang;
|
||||
testDate,
|
||||
_startTime.value,
|
||||
_endTime.value,
|
||||
showCol.value,
|
||||
)
|
||||
|
||||
_nowtime.value = DayJs(testDate)
|
||||
colIndex.value = getIndexNowbydate(testRang, _nowtime.value, showCol.value)
|
||||
emits('update:modelValue', _nowtime.value.format('YYYY/MM/DD HH:mm:ss'))
|
||||
emits('update:modelStr', _nowtime.value.format(props.format))
|
||||
emits('change', _nowtime.value.format(props.format))
|
||||
|
||||
_col.value = testRang
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => {
|
||||
if (!DayJs(props.modelValue).isValid()) return;
|
||||
let deattime = DayJs(checkNowDateisBetween(props.modelValue, props.start, props.end));
|
||||
if (!DayJs(props.modelValue).isValid()) return
|
||||
let deattime = DayJs(
|
||||
checkNowDateisBetween(props.modelValue, props.start, props.end),
|
||||
)
|
||||
|
||||
if (DayJs(deattime).isSame(_nowtime.value)) return;
|
||||
_nowtime.value = deattime;
|
||||
emits("update:modelStr", _nowtime.value.format(props.format));
|
||||
if (DayJs(deattime).isSame(_nowtime.value)) return
|
||||
_nowtime.value = deattime
|
||||
emits('update:modelStr', _nowtime.value.format(props.format))
|
||||
// #ifdef APP-NVUE
|
||||
_col.value = rangeTimeArray(
|
||||
deattime,
|
||||
_startTime.value,
|
||||
_endTime.value,
|
||||
showCol.value
|
||||
);
|
||||
show.value = false;
|
||||
colIndex.value = getIndexNowbydate(_col.value, _nowtime.value, showCol.value);
|
||||
showCol.value,
|
||||
)
|
||||
show.value = false
|
||||
colIndex.value = getIndexNowbydate(
|
||||
_col.value,
|
||||
_nowtime.value,
|
||||
showCol.value,
|
||||
)
|
||||
nextTick(() => {
|
||||
/**这力着重解释下,uni sdk从3.6.8开始,在nvue下直接对picker view赋值value,页面不会有任何变化,必须刷新下页面才可以显示正确
|
||||
* 其它平台没有这问题
|
||||
*/
|
||||
show.value = true;
|
||||
});
|
||||
show.value = true
|
||||
})
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
_col.value = rangeTimeArray(
|
||||
deattime,
|
||||
_startTime.value,
|
||||
_endTime.value,
|
||||
showCol.value
|
||||
);
|
||||
colIndex.value = getIndexNowbydate(_col.value, _nowtime.value, showCol.value);
|
||||
showCol.value,
|
||||
)
|
||||
colIndex.value = getIndexNowbydate(
|
||||
_col.value,
|
||||
_nowtime.value,
|
||||
showCol.value,
|
||||
)
|
||||
// #endif
|
||||
}
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
function nvuegetClientRect() {
|
||||
nextTick(function () {
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
dom.getComponentRect(proxy.$refs.picker, function (res) {
|
||||
if (res?.size) {
|
||||
maskWidth.value = res.size.width;
|
||||
maskWidth.value = res.size.width
|
||||
|
||||
if (res.size.width == 0) {
|
||||
nvuegetClientRect();
|
||||
nvuegetClientRect()
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
// #endif
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nvuegetClientRect();
|
||||
nvuegetClientRect()
|
||||
nextTick(() => {
|
||||
emits("update:modelValue", _nowtime.value.format("YYYY/MM/DD HH:mm:ss"));
|
||||
emits("update:modelStr", _nowtime.value.format(props.format));
|
||||
colIndex.value = getIndexNowbydate(_col.value, _nowtime.value, showCol.value);
|
||||
});
|
||||
});
|
||||
emits('update:modelValue', _nowtime.value.format('YYYY/MM/DD HH:mm:ss'))
|
||||
emits('update:modelStr', _nowtime.value.format(props.format))
|
||||
colIndex.value = getIndexNowbydate(
|
||||
_col.value,
|
||||
_nowtime.value,
|
||||
showCol.value,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
onUpdated(() => nvuegetClientRect());
|
||||
onUpdated(() => nvuegetClientRect())
|
||||
|
||||
// defineExpose({tmTimeViewName,setNowtime})
|
||||
</script>
|
||||
@ -397,7 +425,11 @@ onUpdated(() => nvuegetClientRect());
|
||||
}
|
||||
|
||||
.bottom {
|
||||
background-image: linear-gradient(to top, rgba(17, 17, 17, 1), rgba(36, 36, 36, 0.6));
|
||||
background-image: linear-gradient(
|
||||
to top,
|
||||
rgba(17, 17, 17, 1),
|
||||
rgba(36, 36, 36, 0.6)
|
||||
);
|
||||
}
|
||||
|
||||
.itemcel {
|
||||
|
@ -1,76 +1,120 @@
|
||||
{
|
||||
"language": "简体-中国",
|
||||
"index.search.subtext": "全端兼容vue3 TypeScript pinia组件库",
|
||||
"index.search.tips": "组件中文/英文名称",
|
||||
"index.search.btntext": "搜索组件",
|
||||
"index.com.navtitle": "TMUI 全平台组件库",
|
||||
"index.com.title": "分类导航",
|
||||
"index.com.tongyong": "通用组件",
|
||||
"index.com.tongyongSub": "高频常用组件",
|
||||
"index.com.row": "布局组件",
|
||||
"index.com.rowSub": "布局排版",
|
||||
"index.com.show": "展示组件",
|
||||
"index.com.showSub": "常见数据展示",
|
||||
"index.com.form": "表单录入",
|
||||
"index.com.formSub": "数据提交类",
|
||||
"index.com.fd": "反馈类型",
|
||||
"index.com.fdSub": "提示弹层类组件",
|
||||
"index.com.nav": "导航类型",
|
||||
"index.com.navSub": "分页导航类",
|
||||
"index.com.yewu": "业务型组件",
|
||||
"index.com.yewuSub": "优惠券导购类",
|
||||
"index.com.other": "其它",
|
||||
"index.com.otherSub": "功能型组件",
|
||||
"index.com.tubiao": "图表组件",
|
||||
"index.com.tubiaoSub": "Echarts 5.3.2",
|
||||
"index.com.render": "tmCv",
|
||||
"index.com.renderSub": "canvas动画渲染",
|
||||
"index.com.pag": "PAG",
|
||||
"index.com.pagSub": "腾讯pag动画",
|
||||
"index.com.bottom": "TMUI3.0",
|
||||
"index.com.setLocal": "设置语言",
|
||||
"index.com.autoDark": "暗黑跟随系统",
|
||||
"index.com.love": "TMUI用户中心",
|
||||
"index.com.loveSub": "看广告赚积分",
|
||||
"index.com.themetext": "动态切换主题,默认主题见文档",
|
||||
"index.com.themeGreen": "小黄",
|
||||
"index.com.themeBlue": "蓝色",
|
||||
"index.com.themeRed": "红色",
|
||||
"index.com.themeDefault": "默认",
|
||||
"index.com.themeCustText": "自定",
|
||||
"message.load.text": "加载中",
|
||||
"message.error.text": "操作错误",
|
||||
"message.info.text": "提示信息",
|
||||
"message.warn.text": "警告信息",
|
||||
"message.quest.text": "似乎有问题",
|
||||
"message.success.text": "操作成功",
|
||||
"message.disabled.text": "禁止操作",
|
||||
"message.wait.text": "请稍候..",
|
||||
"index.mine.logOut":"退出登录",
|
||||
"index.mine.help":"帮助中心",
|
||||
"index.mine.settings":"设置与隐私",
|
||||
"index.mine.addressBook":"通讯录",
|
||||
"index.mine.card":"我的名片",
|
||||
"index.mine.information":"个人信息认证",
|
||||
"index.mine.refresh":"刷新缓存",
|
||||
"index.mine.clickRefresh":"点击清理缓存",
|
||||
"index.mine.basic":"基本信息",
|
||||
"index.mine.company":"公司别",
|
||||
"index.mine.department":"部门",
|
||||
"index.mine.post":"岗位",
|
||||
"index.mine.manager":"主管",
|
||||
"index.mine.phone":"手机号",
|
||||
"index.mine.entry":"入职时间",
|
||||
"index.mine.unable":"无法上传照片",
|
||||
"index.mine.face":"扫脸失败",
|
||||
"index.mine.recentPhoto":"个人近照",
|
||||
"userAgreement":"用户服务协议",
|
||||
"privacyPolicy":"隐私政策",
|
||||
"index.mine.cancellation":"注销账号",
|
||||
"ok":"确定",
|
||||
"message.customerService.text":"请拨打客服电话",
|
||||
"message.action.text":"进行注销操作",
|
||||
"index.mine.upload":"点击上传",
|
||||
"index.mine.reUpload":"重新上传",
|
||||
"index.mine.loading":"载入中"
|
||||
"language": "简体-中国",
|
||||
"index.search.subtext": "全端兼容vue3 TypeScript pinia组件库",
|
||||
"index.search.tips": "组件中文/英文名称",
|
||||
"index.search.btntext": "搜索组件",
|
||||
"index.com.navtitle": "TMUI 全平台组件库",
|
||||
"index.com.title": "分类导航",
|
||||
"index.com.tongyong": "通用组件",
|
||||
"index.com.tongyongSub": "高频常用组件",
|
||||
"index.com.row": "布局组件",
|
||||
"index.com.rowSub": "布局排版",
|
||||
"index.com.show": "展示组件",
|
||||
"index.com.showSub": "常见数据展示",
|
||||
"index.com.form": "表单录入",
|
||||
"index.com.formSub": "数据提交类",
|
||||
"index.com.fd": "反馈类型",
|
||||
"index.com.fdSub": "提示弹层类组件",
|
||||
"index.com.nav": "导航类型",
|
||||
"index.com.navSub": "分页导航类",
|
||||
"index.com.yewu": "业务型组件",
|
||||
"index.com.yewuSub": "优惠券导购类",
|
||||
"index.com.other": "其它",
|
||||
"index.com.otherSub": "功能型组件",
|
||||
"index.com.tubiao": "图表组件",
|
||||
"index.com.tubiaoSub": "Echarts 5.3.2",
|
||||
"index.com.render": "tmCv",
|
||||
"index.com.renderSub": "canvas动画渲染",
|
||||
"index.com.pag": "PAG",
|
||||
"index.com.pagSub": "腾讯pag动画",
|
||||
"index.com.bottom": "TMUI3.0",
|
||||
"index.com.setLocal": "设置语言",
|
||||
"index.com.autoDark": "暗黑跟随系统",
|
||||
"index.com.love": "TMUI用户中心",
|
||||
"index.com.loveSub": "看广告赚积分",
|
||||
"index.com.themetext": "动态切换主题,默认主题见文档",
|
||||
"index.com.themeGreen": "小黄",
|
||||
"index.com.themeBlue": "蓝色",
|
||||
"index.com.themeRed": "红色",
|
||||
"index.com.themeDefault": "默认",
|
||||
"index.com.themeCustText": "自定",
|
||||
"message.load.text": "加载中",
|
||||
"message.error.text": "操作错误",
|
||||
"message.info.text": "提示信息",
|
||||
"message.warn.text": "警告信息",
|
||||
"message.quest.text": "似乎有问题",
|
||||
"message.success.text": "操作成功",
|
||||
"message.disabled.text": "禁止操作",
|
||||
"message.wait.text": "请稍候..",
|
||||
"index.mine.logOut": "退出登录",
|
||||
"index.mine.help": "帮助中心",
|
||||
"index.mine.settings": "设置与隐私",
|
||||
"index.mine.addressBook": "通讯录",
|
||||
"index.mine.card": "我的名片",
|
||||
"index.mine.information": "个人信息认证",
|
||||
"index.mine.refresh": "刷新缓存",
|
||||
"index.mine.clickRefresh": "点击清理缓存",
|
||||
"index.mine.basic": "基本信息",
|
||||
"index.mine.company": "公司别",
|
||||
"index.mine.department": "部门",
|
||||
"index.mine.post": "岗位",
|
||||
"index.mine.manager": "主管",
|
||||
"index.mine.phone": "手机号",
|
||||
"index.mine.entry": "入职时间",
|
||||
"index.mine.unable": "无法上传照片",
|
||||
"index.mine.face": "扫脸失败",
|
||||
"index.mine.recentPhoto": "个人近照",
|
||||
"userAgreement": "用户服务协议",
|
||||
"privacyPolicy": "隐私政策",
|
||||
"index.mine.cancellation": "注销账号",
|
||||
"ok": "确定",
|
||||
"message.customerService.text": "请拨打客服电话",
|
||||
"message.action.text": "进行注销操作",
|
||||
"index.mine.upload": "点击上传",
|
||||
"index.mine.reUpload": "重新上传",
|
||||
"index.mine.loading": "载入中",
|
||||
"cancel": "取消",
|
||||
"search.hint": "检索您要查找的内容吧~",
|
||||
"search.chat.count": "条相关聊天记录",
|
||||
"index.mine.project": "项目",
|
||||
"chat.type.group": "群聊",
|
||||
"chat.type.record": "聊天记录",
|
||||
"search.result.include": "包含:",
|
||||
"has_more": "更多",
|
||||
"index.type.company": "公司",
|
||||
"search.result.relevant": "相关",
|
||||
"index.chat.settings": "聊天设置",
|
||||
"chat.settings.clearChatRecord": "清空聊天记录",
|
||||
"chat.settings.groupName": "群名称",
|
||||
"chat.settings.groupNotice": "群公告",
|
||||
"chat.settings.groupType": "群类型",
|
||||
"chat.settings.topSession": "置顶会话",
|
||||
"chat.settings.messageNoDisturb": "消息免打扰",
|
||||
"chat.settings.groupGag": "群内禁言",
|
||||
"chat.settings.groupAdmin": "群管理员",
|
||||
"chat.settings.groupMember": "群成员",
|
||||
"search.chat.record": "搜索聊天记录",
|
||||
"record.searchType.date": "日期",
|
||||
"record.searchType.imgAndVideo": "图片及视频",
|
||||
"record.searchType.files": "文件",
|
||||
"record.searchType.link": "链接",
|
||||
"group.identify.admin": "管理员",
|
||||
"group.disband.btn": "解散该群",
|
||||
"group.quit.btn": "退出群聊",
|
||||
"search.condition.date": "按日期查找",
|
||||
"search.condition.date_pickerTitle": "请选择聊天日期",
|
||||
"button.text.done": "完成",
|
||||
"input.placeholder.enter": "请输入...",
|
||||
"chat.settings.editGroupName": "修改群名称",
|
||||
"edit.groupName.placeholder": "请输入群名称(1~20个字)",
|
||||
"chat.settings.editAvatar": "修改头像",
|
||||
"button.text.edit": "修改",
|
||||
"chat.manage.silenceMember": "被禁言的成员",
|
||||
"chat.manage.silenceAll": "全员禁言",
|
||||
"chat.manage.silenceAllHint": "开启后,只允许群管理员发言",
|
||||
"chat.manage.addSilenceMember": "添加禁言成员",
|
||||
"chatSettings.btn.undoSilence": "解禁",
|
||||
"silence.tag.hasDone": "已禁言",
|
||||
"chat.manage.addAdmin": "添加管理员",
|
||||
"search.condition.member": "按群成员查找"
|
||||
}
|
||||
|