TDesign——Input指定光标插入内容

简介: TDesign——Input指定光标插入内容

前言

setRangeText: setRangeText

在线预览:wordPackage

内容

<template>
  <t-tabs :default-value="1">
    <t-tab-panel :value="1" label="广告创意">
      <template #panel>
        <t-form ref="form" :rules="FORM_RULES" :data="formData" :required-mark="false" @submit="onSubmit">
          <!-- 标题 -->
          <t-card
            :title="`标题(${formData.dynamic_creative_elements.title_options.length}/10)`"
            header-bordered
            :style="{ width: '800px', margin: '20px 0 0 20px' }"
          >
            <t-form-item
              v-for="(titles, index) in formData.titles"
              :key="index"
              label="标题(1-30字)"
              :name="`titles[${index}].title`"
            >
              <t-input
                :id="`title_${index}`"
                v-model="formData.titles[index].title"
                placeholder="请输入标题"
                :maxlength="30"
                show-limit-number
                allow-input-over-max
                @change="handleWordPackageDelete($event, 1, index)"
              />
              <t-dropdown
                :options="wordPackageOptions"
                :min-column-width="100"
                @click="handleWordsPackage($event, 1, index)"
              >
                <span>
                  <t-button variant="text">
                    <template #icon><wallet-icon /></template>
                    插入词包
                  </t-button>
                </span>
              </t-dropdown>
              <span v-if="formData.titles.length > 1" @click="handleRemoveElement(1, index)">
                <t-button shape="square">
                  <template #icon><remove-icon size="2em" /></template>
                </t-button>
              </span>
            </t-form-item>
            <div>
              <t-button block :disabled="formData.titles.length === 10" @click="handleAddElement(1)">
                还可以添加{{ 10 - formData.titles.length }}个
              </t-button>
            </div>
          </t-card>
          <!-- 描述 -->
          <t-card
            :title="`描述(${formData.descriptions.length}/10)`"
            header-bordered
            :style="{ width: '800px', margin: '20px 0 0 20px' }"
          >
            <template #subtitle>
              <t-tooltip theme="light">
                <template #content>
                  <div style="width: 280px">
                    为使展示效果最佳,建议搜一搜描述文案字数 30 字以内
                    <t-image
                      src="https://qzonestyle.gdtimg.com/gdt_ui_proj/imghub/dist/search-desc-tip.png?max_age=31536000"
                    />
                  </div>
                </template>
                <help-circle-icon size="18px" />
              </t-tooltip>
            </template>
            <t-form-item
              v-for="(descriptions, index) in formData.descriptions"
              :key="index"
              label="描述(4-80字)"
              :name="`descriptions[${index}].description`"
            >
              <t-input
                :id="`desc_${index}`"
                v-model="formData.descriptions[index].description"
                placeholder="请输入描述"
                :maxlength="80"
                show-limit-number
                allow-input-over-max
                @change="handleWordPackageDelete($event, 2, index)"
              />
              <t-dropdown
                :options="wordPackageOptions"
                :min-column-width="100"
                @click="handleWordsPackage($event, 2, index)"
              >
                <span>
                  <t-button variant="text">
                    <template #icon><wallet-icon /></template>
                    插入词包
                  </t-button>
                </span>
              </t-dropdown>
              <span v-if="formData.descriptions.length > 1" @click="handleRemoveElement(2, index)">
                <t-button shape="square">
                  <template #icon><remove-icon size="2em" /></template>
                </t-button>
              </span>
            </t-form-item>
            <div>
              <t-button block :disabled="formData.descriptions.length === 10" @click="handleAddElement(2)">
                还可以添加{{ 10 - formData.descriptions.length }}个
              </t-button>
            </div>
          </t-card>
        </t-form>
      </template>
    </t-tab-panel>
  </t-tabs>
  <!-- 插入词包 | 添加关键词弹窗 -->
  <t-dialog
    v-model:visible="addDefaultKeywordVisible"
    @close="handleAddDefaultKeywordCancel"
    @confirm="handleAddDefaultKeywordConfirm"
  >
    <template #header>
      <div>
        <span>添加默认关键词</span>
        <t-tooltip theme="light">
          <template #content>
            <div style="width: 280px">
              插入关键词通配符的创意得到展现时,系统会根据匹配策略,将默认关键词替换为触发的关键词,
              提高创意与用户搜索词之间的相关性,同时创意中和用户搜索词一致的词汇,可能得到飘红展示。
              例如:如果广告主填写了“北京同城{鲜花}配送”,且购买了“玫瑰花”这个关键词,当用户搜索“北京哪里可以送玫瑰花”时,
              广告创意可能以“北京同城玫瑰花配送”展示给用户。即默认关键词“鲜花”被替换成用户搜索词中包含的关键词“玫瑰花”。
              <br />
              请为关键词词包设置默认关键词。触发的关键词替换时,如果用户搜索词过长,
              直接替换可能超过字数限制,或替换后命中审核黑词,此时系统将以广告主设置的默认关键词来替换并展现。
            </div>
          </template>
          <help-circle-icon size="18px" />
        </t-tooltip>
      </div>
    </template>
    <t-input v-model="defaultKeyword" placeholder="请输入关键词" :maxlength="30" show-limit-number />
  </t-dialog>
</template>
<script setup lang="ts">
import {ref} from 'vue'
import { HelpCircleIcon, InfoCircleFilledIcon, RemoveIcon, WalletIcon } from 'tdesign-icons-vue-next';
import { MessagePlugin } from 'tdesign-vue-next';
const props = defineProps({
  promote: Object,
  adcreativeId: String,
});
const formData: any = ref({
  dynamic_creative_elements: {
    title_options: [],
    description_options: [],
    image_options: [],
    video_options: [],
    brand: {
      brand_img: '',
      brand_name: '',
    },
  },
  page_type: 'PAGE_TYPE_CANVAS_WECHAT',
  page_spec: {},
  dynamic_creative_name: '',
  // 数据中转
  titles: [{ title: '' }],
  descriptions: [{ description: '' }],
  images: [],
  videos: [],
  brand: {},
});
const wordPackageOptions = [
  { content: '城市', value: 1, extends: '{{city}}' },
  { content: '日期', value: 2, extends: '{{day}}' },
  { content: '星期', value: 3, extends: '{{week}}' },
  { content: '关键词', value: 4 },
];
const wordPackagesArray = ref(['{{city}}', '{{day}}', '{{week}}']);
const addDefaultKeywordVisible = ref(false);
const defaultKeyword = ref('');
// 处理词包
const handleWordPackageDelete = (val: string, type: number, index: number) => {
  let inputValue = val;
  inputValue = (inputValue += '')
    .replace(/([^{]+|^)({[^{}]*?}+)/g, (e, t) => t)
    .replace(/{{[^{}]*?}([^}]|$)/g, (e, t) => t)
    .replace(/{{([^{}]*?)}}/g, (e) => (wordPackagesArray.value.includes(e) ? e : ''));
  if (type === 1) formData.value.titles[index].title = inputValue;
  if (type === 2) formData.value.descriptions[index].description = inputValue;
};
// 处理取消添加默认关键词
const handleAddDefaultKeywordCancel = () => {
  addDefaultKeywordVisible.value = false;
  defaultKeyword.value = '';
};
// 处理确定添加默认关键词
const handleAddDefaultKeywordConfirm = () => {
  const wordPackages = JSON.parse(localStorage.getItem('wordPackages'));
  const keyword = `{${defaultKeyword.value}}`;
  if (!wordPackagesArray.value.includes(keyword)) wordPackagesArray.value.push(keyword);
  handleWordsPackage({ extends: keyword }, wordPackages.type, wordPackages.index);
  addDefaultKeywordVisible.value = false;
  defaultKeyword.value = '';
};
// 处理词包插入 | NOTE 这里不考虑IE浏览器
const handleWordsPackage = (val: any, type: number, index: number) => {
  localStorage.setItem('wordPackages', JSON.stringify({ type, index }));
  const id = `#${['title_', 'desc_'][type - 1]}${index} input`;
  const input = document.querySelector(id) as HTMLInputElement;
  if (val.value === 4) addDefaultKeywordVisible.value = true;
  else input.setRangeText(val.extends);
  if (type === 1) formData.value.titles[index].title = input.value;
  if (type === 2) formData.value.descriptions[index].description = input.value;
};
// TODO 标题和描述元素抽离成组件
// 处理标题和描述的元素的移除
const handleRemoveElement = (option: number, index: number) => {
  const { titles, descriptions } = formData.value;
  const options = {
    1: () => {
      titles.splice(index, 1);
    },
    2: () => {
      descriptions.splice(index, 1);
    },
  };
  options[option]();
};
// 处理标题和描述的元素添加
const handleAddElement = (option: number) => {
  const { titles, descriptions } = formData.value;
  const options = {
    1: () => {
      titles.push({
        title: '',
      });
    },
    2: () => {
      descriptions.push({
        description: '',
      });
    },
  };
  options[option]();
};
// 表单校验规则
const FORM_RULES = {
  title: [
    { required: true, message: '请输入标题', type: 'error', trigger: 'blur' },
    {
      validator: (val: any) => val.length <= 30,
      message: '标题字数不能超过30字',
      type: 'error',
      trigger: 'change',
    },
  ],
  description: [
    { required: true, message: '请输入描述', type: 'error', trigger: 'blur' },
    {
      validator: (val: any) => val.length <= 80,
      message: '描述字数不能超过80字',
      type: 'error',
      trigger: 'change',
    },
  ],
};
</script>
<style lang="less" scoped>
:deep(.t-tab-panel) {
  margin-left: var(--td-comp-margin-xxxl);
}
.promote-label {
  margin-right: var(--td-comp-margin-xxl);
}
:deep(.t-input) {
  border: transparent;
  border-bottom: 1px solid var(--td-border-level-2-color) !important;
}
:deep(.t-card__title) {
  margin-right: var(--td-comp-margin-xs);
}
:deep(.t-icon) {
  vertical-align: sub;
}
:deep(.t-button--variant-text) {
  border-bottom: 1px solid var(--td-border-level-2-color);
  color: var(--td-text-color-secondary);
}
.sub-text {
  margin-top: 5px;
  font: var(--td-font-body-small);
  color: var(--td-text-color-placeholder);
}
:deep(.t-collapse-panel__icon--left) {
  position: relative;
  top: -26px;
}
.select__overlay-option .t-select-option {
  height: 100%;
  padding: 8px;
}
.user-option-info {
  margin-left: 16px;
}
.user-option {
  display: flex;
}
.select-panel-footer {
  border-top: 1px solid var(--td-component-stroke);
  padding: 6px;
}
</style>

学无止境,谦卑而行.

目录
相关文章
|
前端开发
css改input变输入框光标颜色demo效果示例(整理)
css改input变输入框光标颜色demo效果示例(整理)
|
前端开发
element ui el-table 多选 表头全选框替换文字
element ui el-table 多选 表头全选框替换文字
1642 0
|
3月前
|
JSON 数据格式
Sublime Text 查找的内容 高亮显示
Sublime Text 查找的内容 高亮显示
444 0
Sublime Text 查找的内容 高亮显示
|
4月前
Element UI【级联选择器】el-cascader 获取选中内容的 label 数据,鼠标悬浮显示超长内容
Element UI【级联选择器】el-cascader 获取选中内容的 label 数据,鼠标悬浮显示超长内容
649 3
|
4月前
Element UI 带快捷编辑的多行输入框(含光标位置的获取和指定)
Element UI 带快捷编辑的多行输入框(含光标位置的获取和指定)
30 0
|
5月前
|
JavaScript
jquery在光标位置插入内容指定内容(input、textarea)通用
jquery在光标位置插入内容指定内容(input、textarea)通用
38 0
输入框贴贴去除样式并插入到指定光标位置(contenteditable=“true“ 实现的输入框也支持)
输入框贴贴去除样式并插入到指定光标位置(contenteditable=“true“ 实现的输入框也支持)
105 0
|
JavaScript
js鼠标离开-清除input输入框内的空格demo效果示例(整理)
js鼠标离开-清除input输入框内的空格demo效果示例(整理)
|
前端开发
Element-ui中 实现多选表格(Table)增加 ‘全选’ 字样
Element-ui中 实现多选表格(Table)增加 ‘全选’ 字样
1189 0
Element-ui中 实现多选表格(Table)增加 ‘全选’ 字样
JavaScrip - tab栏切换案例
JavaScrip - tab栏切换案例
115 0