| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- <template>
- <Popup
- :show="show"
- position="bottom"
- size="90vh"
- >
- <ActionSheetTitle
- title="编辑"
- cancelText="取消"
- confirmText="保存"
- @cancel="cancel"
- @confirm="save"
- />
- <sp-editor
- :toolbar-config="{
- excludeKeys: ['direction', 'date', 'lineHeight', 'letterSpacing', 'listCheck'],
- iconSize: '18px'
- }"
- @init="initEditor"
- @input="inputOver"
- @upinImage="upinImage"
- @overMax="overMax"
- ></sp-editor>
- </Popup>
- <view class="d-flex flex-col">
- <view class="richtext-preview-box" @click.stop="edit">
- <Parse v-if="modelValue" :content="modelValue" contentStyle="max-height:400px;overflow:hidden;" />
- <Text v-else color="text.second">{{placeholder}}</Text>
- <div class="richtext-preview-box-fade"></div>
- </view>
- <view class="d-flex flex-row gap-sss align-center mt-2">
- <Button icon="edit" text="编辑" size="small" type="primary" @click.stop="edit" />
- </view>
- </view>
- </template>
- <script setup lang="ts">
- import Popup from '@/components/dialog/Popup.vue';
- import spEditor from '@/uni_modules/sp-editor/components/sp-editor/sp-editor.vue';
- import ActionSheetTitle from '@/components/dialog/ActionSheetTitle.vue';
- import { ref } from 'vue';
- import { confirm, toast } from '@/components/utils/DialogAction';
- import CommonContent from '@/api/CommonContent';
- import Parse from '@/components/display/parse/Parse.vue';
- import Text from '@/components/basic/Text.vue';
- import Button from '@/components/basic/Button.vue';
- const show = ref(false);
- const props = defineProps({
- modelValue: {
- type: String,
- default: null
- },
- maxLength: {
- type: Number,
- default: -1,
- },
- placeholder: {
- type: String,
- default: '未编写内容,点击编写',
- },
- })
- const emit = defineEmits(['update:modelValue'])
- function edit() {
- show.value = true;
- setTimeout(() => {
- }, 200);
- }
- function cancel() {
- confirm({
- title: '提示',
- content: '是否放弃编辑?',
- }).then((res) => {
- if (res)
- show.value = false;
- })
- }
- function save() {
- emit('update:modelValue', currentContent);
- show.value = false;
- }
- let currentContent = '';
- let currentEditor: any = null;
- /**
- * 获取输入内容
- */
- function inputOver(e: { html: string; text: string; }) {
- // 可以在此处获取到编辑器已编辑的内容
- currentContent = e.html;
- }
- /**
- * 超出最大内容限制
- * @param {Object} e {html,text} 内容的html文本,和text文本
- */
- function overMax(e: { html: string; text: string; }) {
- // 若设置了最大字数限制,可在此处触发超出限制的回调
- console.log('==== overMax :', e)
- }
- function initEditor(editor: any) {
- editor.setContents({
- html: props.modelValue
- })
- }
- /**
- * 直接运行示例工程插入图片无法正常显示的看这里
- * 因为插件默认采用云端存储图片的方式
- * 以$emit('upinImage', tempFiles, this.editorCtx)的方式回调
- * @param {Object} tempFiles
- * @param {Object} editorCtx
- */
- function upinImage(tempFiles: any, editorCtx: any) {
- CommonContent.uploadFile(
- // #ifdef MP-WEIXIN
- // 注意微信小程序的图片路径是在tempFilePath字段中
- tempFiles[0].tempFilePath
- // #endif
- // #ifndef MP-WEIXIN
- tempFiles[0].path
- // #endif
- , 'image', 'file').then((res) => {
- editorCtx.insertImage({
- src: res.fullurl,
- width: '80%', // 默认不建议铺满宽度100%,预留一点空隙以便用户编辑
- success: function () {}
- })
- }).catch((err) => {
- toast('上传图片失败')
- console.error('uploadFile error', err);
- });
- return;
- }
- </script>
- <style lang="scss" scoped>
- .richtext-preview-box {
- position: relative;
- flex: 1;
- min-height: 400rpx;
- .richtext-preview-box-fade {
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 100rpx;
- background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1));
- }
- }
- </style>
|