|  | @@ -2,6 +2,7 @@
 | 
	
		
			
				|  |  |    <div>
 | 
	
		
			
				|  |  |      <el-form-item label="序号" class="serial-number">
 | 
	
		
			
				|  |  |        <el-input v-model="propertyObj.serial_number" @input="changeSerialNumber" />
 | 
	
		
			
				|  |  | +      <SvgIcon icon-class="switch" height="16" width="16" @click="switchFormat" />
 | 
	
		
			
				|  |  |      </el-form-item>
 | 
	
		
			
				|  |  |      <el-form-item>
 | 
	
		
			
				|  |  |        <el-radio
 | 
	
	
		
			
				|  | @@ -52,6 +53,9 @@ export default {
 | 
	
		
			
				|  |  |      return {
 | 
	
		
			
				|  |  |        displayList,
 | 
	
		
			
				|  |  |        propertyObj: this.property,
 | 
	
		
			
				|  |  | +      displayValue: '1',
 | 
	
		
			
				|  |  | +      currentFormat: 0, // 0: 数字, 1: 字母, 2: 中文
 | 
	
		
			
				|  |  | +      maxNumber: 99,
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |    watch: {
 | 
	
	
		
			
				|  | @@ -99,6 +103,131 @@ export default {
 | 
	
		
			
				|  |  |        this.updateProperty('sn_style', sn_style);
 | 
	
		
			
				|  |  |        this.updateProperty('sn_background_color', sn_background_color);
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 切换序号显示形式
 | 
	
		
			
				|  |  | +    handleInput(e) {
 | 
	
		
			
				|  |  | +      if (this.currentFormat === 0) {
 | 
	
		
			
				|  |  | +        const inputValue = e.target.value;
 | 
	
		
			
				|  |  | +        if (inputValue === '') {
 | 
	
		
			
				|  |  | +          this.propertyObj.serial_number = '';
 | 
	
		
			
				|  |  | +          return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        const num = parseInt(inputValue);
 | 
	
		
			
				|  |  | +        if (isNaN(num)) {
 | 
	
		
			
				|  |  | +          return;
 | 
	
		
			
				|  |  | +        } else if (num < 1) {
 | 
	
		
			
				|  |  | +          this.propertyObj.serial_number = '1';
 | 
	
		
			
				|  |  | +        } else if (num > this.maxNumber) {
 | 
	
		
			
				|  |  | +          this.propertyObj.serial_number = this.maxNumber.toString();
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          this.propertyObj.serial_number = inputValue;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 切换格式
 | 
	
		
			
				|  |  | +    switchFormat() {
 | 
	
		
			
				|  |  | +      // 获取当前数字值
 | 
	
		
			
				|  |  | +      const num = this.getCurrentNumber() || 1;
 | 
	
		
			
				|  |  | +      // 循环切换格式
 | 
	
		
			
				|  |  | +      this.currentFormat = (this.currentFormat + 1) % 3;
 | 
	
		
			
				|  |  | +      // 更新显示值
 | 
	
		
			
				|  |  | +      switch (this.currentFormat) {
 | 
	
		
			
				|  |  | +        case 0: // 数字
 | 
	
		
			
				|  |  | +          this.propertyObj.serial_number = num.toString();
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 1: // 字母
 | 
	
		
			
				|  |  | +          this.propertyObj.serial_number = this.toLetters(num);
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        case 2: // 中文
 | 
	
		
			
				|  |  | +          this.propertyObj.serial_number = this.toChinese(num);
 | 
	
		
			
				|  |  | +          break;
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +          this.propertyObj.serial_number = num.toString();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 获取当前显示值对应的数字
 | 
	
		
			
				|  |  | +    getCurrentNumber() {
 | 
	
		
			
				|  |  | +      switch (this.currentFormat) {
 | 
	
		
			
				|  |  | +        case 0: {
 | 
	
		
			
				|  |  | +          // 数字
 | 
	
		
			
				|  |  | +          const num = parseInt(this.propertyObj.serial_number);
 | 
	
		
			
				|  |  | +          return isNaN(num) ? null : num;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        case 1: // 字母转数字
 | 
	
		
			
				|  |  | +          return this.lettersToNumber(this.propertyObj.serial_number);
 | 
	
		
			
				|  |  | +        case 2: // 中文转数字
 | 
	
		
			
				|  |  | +          return this.chineseToNumber(this.propertyObj.serial_number);
 | 
	
		
			
				|  |  | +        default:
 | 
	
		
			
				|  |  | +          return null;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 数字转字母 (1→a, 2→b, ..., 27→aa)
 | 
	
		
			
				|  |  | +    toLetters(num) {
 | 
	
		
			
				|  |  | +      if (num < 1) return '';
 | 
	
		
			
				|  |  | +      let result = '';
 | 
	
		
			
				|  |  | +      let n = num - 1;
 | 
	
		
			
				|  |  | +      do {
 | 
	
		
			
				|  |  | +        result = String.fromCharCode(97 + (n % 26)) + result;
 | 
	
		
			
				|  |  | +        n = Math.floor(n / 26) - 1;
 | 
	
		
			
				|  |  | +      } while (n >= 0);
 | 
	
		
			
				|  |  | +      return result;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 字母转数字 (a→1, b→2, ..., aa→27)
 | 
	
		
			
				|  |  | +    lettersToNumber(letters) {
 | 
	
		
			
				|  |  | +      if (!letters || typeof letters !== 'string') return null;
 | 
	
		
			
				|  |  | +      let result = 0;
 | 
	
		
			
				|  |  | +      for (let i = 0; i < letters.length; i++) {
 | 
	
		
			
				|  |  | +        const code = letters.toLowerCase().charCodeAt(i) - 96;
 | 
	
		
			
				|  |  | +        if (code < 1 || code > 26) return null;
 | 
	
		
			
				|  |  | +        result = result * 26 + code;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return result > this.maxNumber ? null : result;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 数字转中文 (1→一, 11→十一, 21→二十一)
 | 
	
		
			
				|  |  | +    toChinese(num) {
 | 
	
		
			
				|  |  | +      const chinese = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
 | 
	
		
			
				|  |  | +      if (num <= 10) return chinese[num];
 | 
	
		
			
				|  |  | +      if (num < 20) return `十${num % 10 === 0 ? '' : chinese[num % 10]}`;
 | 
	
		
			
				|  |  | +      if (num < 100) {
 | 
	
		
			
				|  |  | +        return `${chinese[Math.floor(num / 10)]}十${num % 10 === 0 ? '' : chinese[num % 10]}`;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      return num.toString();
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 中文转数字 (一→1, 十一→11, 二十一→21)
 | 
	
		
			
				|  |  | +    chineseToNumber(text) {
 | 
	
		
			
				|  |  | +      const map = { 零: 0, 一: 1, 二: 2, 三: 3, 四: 4, 五: 5, 六: 6, 七: 7, 八: 8, 九: 9, 十: 10 };
 | 
	
		
			
				|  |  | +      if (!text || typeof text !== 'string') return null;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (text === '十') return 10;
 | 
	
		
			
				|  |  | +      if (text.length === 1) return map[text] || null;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      if (text.startsWith('十')) {
 | 
	
		
			
				|  |  | +        return 10 + (map[text.slice(1)] || 0);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (text.endsWith('十')) {
 | 
	
		
			
				|  |  | +        return (map[text.slice(0, -1)] || 0) * 10;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      const index = text.indexOf('十');
 | 
	
		
			
				|  |  | +      if (index !== -1) {
 | 
	
		
			
				|  |  | +        return (map[text.slice(0, index)] || 0) * 10 + (map[text.slice(index + 1)] || 0);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      return null;
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    },
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  </script>
 | 
	
		
			
				|  |  | +<style lang="scss" scoped>
 | 
	
		
			
				|  |  | +@use '@/styles/mixin.scss' as *;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +.el-form {
 | 
	
		
			
				|  |  | +  @include setting-base;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +</style>
 |