| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- import Vue from 'vue'
- import { getPinyin } from '@/api/base'
- /**
- * 提取拼音首字母
- * @param {string} text - 中文字符串
- * @returns {string} 拼音首字母大写字符串
- */
- function extractFirstLetters(text) {
- // 简单的拼音首字母映射表(常用汉字)
- const pinyinMap = {
- // 这里可以添加更多常用汉字的映射
- }
- // 基础实现:使用正则提取汉字并获取首字母
- // 注意:这只是一个简单的实现,完整的实现需要更全的汉字映射表或使用专业的拼音库
- let result = ''
- const reg = /[\u4e00-\u9fa5]/g
- const matches = text.match(reg)
- if (matches) {
- // 如果有后端接口,则优先使用后端接口
- // 否则使用简单的前端实现
- matches.forEach((char) => {
- // 这里使用一个简单的方法来获取拼音首字母
- // 实际应用中可以使用更完善的拼音库
- const code = char.charCodeAt(0)
- if (code >= 0x4e00 && code < 0x9fa5) {
- // 这里是一个简化的实现,实际项目中建议使用完整的拼音库
- // 或者使用后端接口获取准确的拼音
- result += String.fromCharCode(65 + ((code - 0x4e00) % 26))
- }
- })
- }
- return result.toUpperCase()
- }
- // 创建拼音缩写指令
- Vue.directive('pinyin-abbreviation', {
- // 绑定指令时执行
- bind(el, binding, vnode) {
- // 获取目标输入框
- let target = el
- if (el.tagName !== 'INPUT' && el.tagName !== 'TEXTAREA') {
- target = el.querySelector('input, textarea')
- }
- if (!target) return
- // 获取配置选项
- const options = binding.value || {}
- const targetInput = options.target || null // 目标输入框的v-model字段名
- const uppercase = options.uppercase === true // 是否大写,默认为false
- const useBackend = options.useBackend !== false // 是否使用后端接口,默认为true
- // 处理输入事件
- const handleInput = async (e) => {
- const chineseText = e.target.value
- let abbreviation = ''
- if (useBackend) {
- try {
- // 调用后端接口获取拼音
- const response = await getPinyin(chineseText)
- // 修改: 正确处理响应数据,不再假设存在value字段
- if (response) {
- // 如果响应直接是字符串
- if (typeof response === 'string') {
- abbreviation = response
- }
- // 如果响应是对象且包含data字段
- else if (response.data) {
- abbreviation = response.data
- }
- // 如果响应是对象且包含value字段
- else if (response.value) {
- abbreviation = response.value
- }
- }
- } catch (error) {
- console.error('获取拼音失败,使用前端备用方案', error)
- // 失败时使用前端备用方案
- abbreviation = extractFirstLetters(chineseText)
- }
- } else {
- // 直接使用前端实现
- abbreviation = extractFirstLetters(chineseText)
- }
- // 根据配置决定是否大写
- if (uppercase) {
- abbreviation = abbreviation.toUpperCase()
- }
- // 如果指定了目标输入框,则将结果设置到目标
- if (targetInput && vnode.context) {
- try {
- // 处理嵌套属性路径,如 'formData.alias'
- const pathParts = targetInput.split('.')
- let currentObj = vnode.context
- // 遍历路径,直到倒数第二个属性
- for (let i = 0; i < pathParts.length - 1; i++) {
- const part = pathParts[i]
- // 确保中间对象存在
- if (!currentObj[part]) {
- currentObj[part] = {}
- }
- currentObj = currentObj[part]
- }
- // 获取最后一个属性名
- const lastPart = pathParts[pathParts.length - 1]
- // 使用 Vue 的 set 方法确保响应式更新
- if (vnode.context.$set && currentObj) {
- vnode.context.$set(currentObj, lastPart, abbreviation)
- } else if (currentObj) {
- // 兼容性处理,直接赋值
- currentObj[lastPart] = abbreviation
- }
- } catch (e) {
- console.error(`设置目标字段 ${targetInput} 失败:`, e)
- // 失败时回退到 dataset 存储
- el.dataset.pinyinAbbreviation = abbreviation
- }
- } else {
- // 否则可以将结果存储到某个属性中供使用
- el.dataset.pinyinAbbreviation = abbreviation
- }
- }
- // 添加事件监听器
- target.addEventListener('input', handleInput)
- // 存储处理函数,以便在解绑时移除
- el._pinyinInputHandler = handleInput
- // 如果元素已经有值,初始化时就处理一次
- if (target.value) {
- handleInput({ target })
- }
- },
- // 更新指令时执行
- update(el, binding) {
- // 可以在这里处理指令值变化的逻辑
- },
- // 解绑指令时执行
- unbind(el) {
- // 获取目标输入框
- let target = el
- if (el.tagName !== 'INPUT' && el.tagName !== 'TEXTAREA') {
- target = el.querySelector('input, textarea')
- }
- // 移除事件监听器
- if (target && el._pinyinInputHandler) {
- target.removeEventListener('input', el._pinyinInputHandler)
- delete el._pinyinInputHandler
- }
- },
- })
- // 同时导出一个工具函数供组件内使用
- export function getPinyinAbbreviation(text, options = {}) {
- const { useBackend = false, uppercase = false } = options
- if (useBackend) {
- // 如果需要异步获取,这里返回一个Promise
- return new Promise((resolve, reject) => {
- getPinyin(text)
- .then((response) => {
- if (response) {
- let result = ''
- // 如果响应直接是字符串
- if (typeof response === 'string') {
- result = response
- }
- // 如果响应是对象且包含data字段
- else if (response.data) {
- result = response.data
- }
- // 如果响应是对象且包含value字段
- else if (response.value) {
- result = response.value
- }
- resolve(uppercase ? result.toUpperCase() : result)
- } else {
- resolve('')
- }
- })
- .catch((error) => {
- console.error('获取拼音失败', error)
- // 失败时使用前端备用方案
- const fallbackResult = extractFirstLetters(text)
- resolve(uppercase ? fallbackResult.toUpperCase() : fallbackResult)
- })
- })
- } else {
- // 同步获取
- const result = extractFirstLetters(text)
- return uppercase ? result.toUpperCase() : result
- }
- }
|