| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- <template>
- <view
- class="footer_input"
- :class="[
- bottomHeight == 0 ? 'iosBottom' : '',
- isFocused && bottomHeight && systemInfoName.osName == 'ios'
- ? 'focused'
- : '',
- ]"
- id="chatBottom"
- :style="{
- bottom: bottomHeight + 'px',
- '--bottomHeight': allHeight.keyboardHeight + 'px',
- }"
- >
- <view class="footer_">
- <view class="inputs">
- <up-textarea
- :disabled="disabled"
- v-model="inputValue"
- maxlength="-1"
- :placeholder="$t(placeholder)"
- :adjustPosition="useGlobal().adjustPosition"
- confirm-type="send"
- :showConfirmBar="false"
- :ignoreCompositionEvent="false"
- autoHeight
- @linechange="heightChange"
- @focus="isFocused = true"
- @blur="onBlur"
- @keyboardheightchange="keyboardheightchange"
- @update:modelValue="input"
- @confirm="submit"
- @submit="submit"
- />
- </view>
- <view class="footer_btns">
- <view class="footer_icon" @click="imageUploader">
- <image class="img" src="@/static/chat/chat_add-icon.png"></image>
- </view>
- <view class="footer_send_btn" @click="submit">
- <image
- class="img"
- src="@/static/chat/arrows_up-icon.png"
- mode="heightFix"
- ></image>
- </view>
- </view>
- </view>
- </view>
- <CameraUpload ref="cameraUploadRef" @confirm="onCameraConfirm" />
- </template>
- <script setup>
- import {
- query,
- useGlobal,
- uploadChooseImage,
- $upload,
- debounce,
- systemInfo,
- } from "@/utils";
- import { ref, reactive, nextTick, onMounted } from "vue";
- import { onShow } from "@dcloudio/uni-app";
- import CameraUpload from "./CameraUpload.vue";
- const props = defineProps({
- disabled: {
- type: Boolean,
- default: false,
- },
- placeholder: {
- type: String,
- default: "请输入消息内容",
- },
- modelValue: {
- type: [String, Number],
- default: "",
- },
- bottomHeight: {
- type: Number,
- default: 0,
- },
- });
- const emit = defineEmits([
- "update:modelValue",
- "heights",
- "linechange",
- "submit",
- "imageUp",
- ]);
- const inputValue = ref(props.modelValue);
- const allHeight = reactive({
- height: 0,
- keyboardHeight: 0,
- });
- const isFocused = ref(false);
- const systemInfoName = systemInfo();
- const clear = () => {
- inputValue.value = "";
- };
- function isIOS() {
- const userAgent = navigator.userAgent.toLowerCase();
- return /iphone|ipad|ipod|ios/.test(userAgent);
- }
- const emitHeights = debounce((heightData) => {
- if (!props.disabled) {
- emit("heights", heightData);
- }
- }, 100);
- const submit = () => {
- if (!inputValue.value.replace(/\s+/g, "")) return;
- if (!props.disabled) {
- emit("submit");
- }
- };
- const input = (value) => {
- inputValue.value = value;
- emit("update:modelValue", value);
- };
- const getHeight = (id = "#chatBottom") => {
- try {
- nextTick(async () => {
- const res = await query(id);
- allHeight.height = res.height;
- emitHeights(allHeight);
- });
- } catch (error) {}
- };
- const keyboardheightchange = (e) => {
- nextTick(() => {
- const systemInfo = uni.getSystemInfoSync();
- const bottomSafeDistance =
- systemInfo.screenHeight - systemInfo.safeArea.bottom;
- allHeight.keyboardHeight =
- e.detail.height -
- (systemInfo.platform === "ios" && isFocused.value
- ? bottomSafeDistance
- : 0);
- allHeight.bottomSafeDistance = isFocused.value && bottomSafeDistance;
- emitHeights(allHeight);
- });
- };
- const onBlur = (e) => {
- isFocused.value = false;
- keyboardheightchange(e);
- };
- const heightChange = (e) => {
- getHeight();
- emit("linechange", { detail: e.detail });
- };
- const cameraUploadRef = ref(null);
- const imageUploader = () => {
- if (!props.disabled) {
- cameraUploadRef.value && cameraUploadRef.value.open();
- }
- };
- const onCameraConfirm = (url) => {
- nextTick(() => {
- emit("imageUp", url);
- });
- };
- onMounted(() => {
- nextTick(() => {
- getHeight();
- });
- });
- defineExpose({
- getHeight,
- clear,
- });
- </script>
- <style lang="less" scoped>
- @import url("@/style.less");
- .footer_input {
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- .ver();
- padding: 0 30rpx;
- background-color: #fafafa;
- overflow: hidden;
- z-index: 9999;
- &.iosBottom {
- padding-bottom: constant(safe-area-inset-bottom);
- padding-bottom: env(safe-area-inset-bottom);
- }
- &.focused {
- /* #ifdef APP-PLUS */
- bottom: calc(var(--bottomHeight) + env(safe-area-inset-bottom)) !important;
- /* #endif */
- }
- .footer_ {
- .ver(flex-end);
- flex: 1;
- padding: 20rpx 0;
- .inputs {
- min-height: 40px;
- flex: 1;
- /deep/ .u-textarea {
- padding: 9px;
- .uni-textarea-placeholder {
- line-height: 1.2;
- }
- .u-textarea__field {
- min-height: 0 !important;
- }
- }
- }
- .footer_btns {
- .ver();
- height: 40px;
- margin-left: 20rpx;
- .footer_icon {
- .img {
- width: 38rpx;
- height: 38rpx;
- }
- }
- .footer_send_btn {
- .flex_center();
- width: 68rpx;
- height: 68rpx;
- border-radius: 50%;
- background-color: var(--black);
- cursor: pointer;
- margin-left: 15rpx;
- .img {
- height: 32rpx;
- }
- }
- }
- }
- }
- </style>
|