提交 33ae4eca authored 作者: 张烨's avatar 张烨

feat:市场准入限制-修改232调查统计

上级 32381f85
......@@ -190,6 +190,14 @@ export function getSearchBlurb(params) {
})
}
// 获取原文
export function getOriginalUrl(params) {
return request({
method: 'GET',
url: `/api/marketsearchDetails/getOriginalUrl/${params.id}`,
})
}
// 获取相关事件
export function getRelatedEvents(params) {
return request({
......
......@@ -6,6 +6,7 @@ const MarketAccessCase = () => import('@/views/marketAccessRestrictions/marketAc
const MarketSingleCaseLayout = () => import('@/views/marketAccessRestrictions/singleCaseLayout/index.vue')
const MarketSingleCaseOverview = () => import('@/views/marketAccessRestrictions/singleCaseLayout/overview/index.vue')
const MarketSingleCaseDeepdig = () => import('@/views/marketAccessRestrictions/singleCaseLayout/deepdig/index.vue')
const MarketSingleReportOriginal = () => import('@/views/marketAccessRestrictions/pages/reportOriginal.vue')
const marketAccessRestrictionsRoutes = [
// 市场准入限制首页
......@@ -42,7 +43,6 @@ const marketAccessRestrictionsRoutes = [
}
]
},
{
path: "/marketSingleCaseLayout",
name: "MarketSingleCaseLayout",
......@@ -67,7 +67,12 @@ const marketAccessRestrictionsRoutes = [
}
]
},
{
path: "reportOriginal",
name: "MarketSingleReportOriginal",
component: MarketSingleReportOriginal,
meta: { noTitle: true }
}
]
export default marketAccessRestrictionsRoutes
\ No newline at end of file
......@@ -53,7 +53,7 @@
<div v-for="(subSubItem, subSubIndex) in subItem.slaver" :key="subSubIndex"
class="sub-sub-item">
<div class="sub-sub-item-dot">{{ ALPHABET[subSubIndex % 26] }}.</div>
<div class="sub-sub-item-word" v-html="subItem.content"></div>
<div class="sub-sub-item-word" v-html="subSubItem.content"></div>
</div>
</div>
</div>
......@@ -157,6 +157,7 @@ import ActionButton from '@/components/base/ActionButton/index.vue'
import DefaultIcon1 from "@/assets/icons/default-icon1.png";
import DefaultIcon2 from "@/assets/icons/default-icon2.png";
import defaultCom from "@/views/coopRestriction/assets/images/default-icon2.png"
import { onNumToChinese } from "@/views/marketAccessRestrictions/utils/index"
const route = useRoute();
......@@ -185,70 +186,7 @@ const handleGetAreaList = async () => {
// 主要指令
const isHighlight = ref(false);
const commandWord = ref("");
const contentList = ref([
// {
// content: "建立美国人工智能出口计划建立美国人工智能出口计划建立美国人工智能出口计划建立美国人工智能出口计划建立美国人工智能出口计划",
// slaver: [
// {
// content: '在本命令发布之日起 90 天内,商务部长应与国务卿及科学技术政策办公室(OSTP)主任协商,建立并实施美国人工智能出口计划(计划),以支持美国全栈人工智能出口软件包的开发和部署。'
// },
// {
// content: '商务部长应公开征集由行业主导的联盟提案,以纳入该计划。公开征集要求每项提案必须:',
// slaver: [
// {
// content: '包含一套全栈人工智能技术包,涵盖:',
// slaver: [
// {
// content: 'AI 优化的计算机硬件(如芯片、服务器和加速器)、数据中心存储、云服务和网络,以及这些设备是否以及在多大程度上在美国制造的描述;'
// },
// {
// content: '数据管道和标签系统;'
// },
// {
// content: '人工智能模型与系统;'
// },
// {
// content: '采取措施保障人工智能模型和系统的安全性和网络安全;'
// },
// {
// content: '针对特定用例的人工智能应用(如软件工程、教育、医疗保健、农业或交通运输);'
// }
// ]
// },
// {
// content: '确定出口参与者的具体目标国家或区域集团;'
// },
// {
// content: '描述一个业务和运营模型,以在高层次上说明哪些实体将建设、拥有和运营数据中心及相关基础设施;'
// },
// {
// content: '联邦激励和支持机制请求的细节;'
// },
// {
// content: '遵守所有相关的美国出口管制制度、出境投资法规和终端用户政策,包括美国法典第 50 编第 58 章及商务部工业与安全局的相关指导。'
// }
// ]
// },
// {
// content: '商务部要求提案须在公开征集后不超过 90 天内提交,并应滚动考虑提案纳入项目。'
// },
// {
// content: '商务部长应与国务卿、国防部长、能源部长及 OSTP 主任协商,评估提交的纳入计划提案。商务部长与国务卿、国防部长、能源部长及 OSTP 主任协商后选定的提案,将被指定为优先 AI 出口包,并通过优先访问本命令第 4 节指定的工具予以支持,符合适用法律。'
// }
// ]
// },
// {
// content: "动员联邦融资工具",
// slaver: [
// {
// content: '经济外交行动小组(EDAG),于 2024 年 6 月 21 日总统备忘录中成立,由国务卿主持,并与商务部长和美国贸易代表协商,并根据 2019 年《通过外交倡导美国企业法案》(公共法 116-94 J 部分第七章)第 708 条(CABDA)所述,应协调联邦融资工具的动员,以支持优先的人工智能出口方案。'
// },
// {
// content: '我将根据 CABDA α 第 708 (c) (3) 条授权小企业管理局局长和 OSTP 主任任命各自执行部门和机构的高级官员担任 EDAG 。'
// }
// ]
// }
]);
const contentList = ref([]);
const ALPHABET = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
const onMainContentData = async () => {
try {
......@@ -257,7 +195,7 @@ const onMainContentData = async () => {
console.log("主要指令", res);
if (res && res.code === 200) {
contentList.value = res.data || [];
contentList.value.forEach((item, index) => { item.content = `(${simpleNumToChinese(index + 1)}) ${item.content}` })
contentList.value.forEach((item, index) => { item.content = `(${onNumToChinese(index + 1)}) ${item.content}` })
if (keyword) {
let word = keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
contentList.value.forEach(item => { onHighlight(word, item) })
......@@ -279,30 +217,6 @@ const onHighlight = (word, row) => {
row.slaver.forEach(item => { onHighlight(word, item) })
}
}
// 数字转中文(支持 0-99 整数)
const simpleNumToChinese = (num) => {
// 1. 基础校验:只处理 0-99 的整数
if (!Number.isInteger(num) || num < 0 || num > 99) return '100';
// 2. 定义基础字符
const singleChars = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
const tenChar = '十';
// 3. 核心转换逻辑
if (num < 10) {
// 0-9 直接返回对应字符
return singleChars[num];
} else if (num === 10) {
// 10 特殊处理
return tenChar;
} else if (num < 20) {
// 11-19:十 + 个位(如十一、十九)
return tenChar + singleChars[num - 10];
} else {
// 20-99:十位 + 十 + 个位(个位为0则省略,如二十、二十九)
const ten = Math.floor(num / 10); // 十位数字
const unit = num % 10; // 个位数字
return singleChars[ten] + tenChar + (unit === 0 ? '' : singleChars[unit]);
}
}
// 思维导图
const isTreeDialog = ref(false);
......
......@@ -5,8 +5,8 @@
<div class="data-list">
<div class="data-item" v-for="(item, index) in props.listData" :key="index">
<div class="item-head">
<div class="item-name">{{ item.title }}</div>
<div class="button-box">
<div class="item-name">{{ `(${onNumToChinese(Number(index)+1)}). ${item.title}` }}</div>
<div class="button-box" @click="onNavigateTo(item)">
<div class="button-icon">
<img src="../assets/icons/open.png" alt="" />
</div>
......@@ -14,7 +14,10 @@
</div>
</div>
<div class="item-down">
<div class="item-text" v-for="(text, num) in item.data" :key="num">{{ text }}</div>
<div class="item-info" v-for="(text, num) in item.data" :key="num">
<div class="item-num">{{ Number(num) + 1 }}.</div>
<div class="text-align-justify">{{ text }}</div>
</div>
</div>
</div>
</div>
......@@ -25,6 +28,10 @@
<script setup lang="ts" name="SurveyConclusion">
import AiTips from "@/views/marketAccessRestrictions/com/AiTips.vue";
import { onNumToChinese } from "@/views/marketAccessRestrictions/utils/index"
import router from "@/router";
import { useRoute } from "vue-router";
const route = useRoute();
const props = defineProps({
listData: {
......@@ -41,6 +48,15 @@ const props = defineProps({
}
})
const onNavigateTo = (item:any) => {
console.log(item)
const page = router.resolve({
name: "MarketSingleReportOriginal",
query: { ...route.query }
});
window.open(page.href, "_blank");
}
</script>
<style scoped lang="scss">
......@@ -70,6 +86,7 @@ const props = defineProps({
display: flex;
align-items: center;
margin-left: 50px;
cursor: pointer;
.button-icon {
width: 16px;
height: 16px;
......@@ -89,17 +106,21 @@ const props = defineProps({
}
}
}
.item-text {
letter-spacing: 1px;
padding: 12px 20px 12px 40px;
.item-info {
padding: 12px 20px 12px 50px;
color: rgba(59, 65, 75, 1);
font-family: Source Han Sans CN;
font-size: 16px;
font-weight: 400;
line-height: 30px;
letter-spacing: 0px;
text-align: justify;
border-bottom: 1px solid rgba(234, 236, 238, 1);
position: relative;
.item-num {
position: absolute;
left: 26px;
top: 12px;
}
}
}
}
......
......@@ -278,8 +278,8 @@ import CarouselItem232 from '@/views/marketAccessRestrictions/marketAccessHome/c
import setChart from "@/utils/setChart";
import router from "@/router";
import createLineChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/basePiechart.js";
import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
import getRadarChart from "./utils/radarChart";
import getBarChart from "./utils/barChart1";
......
......@@ -19,8 +19,7 @@
<div class="page-tabs">
<div :class="['tab-item', {'tab-active': activeName==item.name}]" v-for="(item, index) in tabList" :key="index" @click="handleClickBtn(item)">
<div class="icon">
<img :src="item.activeIcon" alt="" v-if="activeName==item.name" />
<img :src="item.icon" alt="" v-else />
<img :src="activeName==item.name ? item.activeIcon : item.icon" alt="" />
</div>
<div class="text" :class="{ textActive: activeName==item.name }">
{{ item.name }}
......
......@@ -75,8 +75,8 @@ import {
getSearchTariff,
} from "@/api/marketAccessRestrictions";
import createLineChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/basePiechart.js";
import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
// 数量统计
const totalCaseNum = ref(0)
......
......@@ -58,8 +58,8 @@ import {
getStatNum,
getSearchDirection
} from "@/api/marketAccessRestrictions";
import createLineChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/basePiechart.js";
import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
const inProgressCount = ref(0);
const box1Loading = ref(false);
......
......@@ -88,8 +88,8 @@ import TipTab from "@/components/base/TipTab/index.vue"
import { getStatCount, getStatcnOrgCount, getSearchResult, getStatArea, getStatNum } from "@/api/marketAccessRestrictions";
import createLineChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/marketAccessHome/utils/basePiechart.js";
import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChart";
import createPieChart from "@/views/marketAccessRestrictions/utils/basePiechart.js";
import getBarChart from "./utils/barChart";
import getMapChart from "./utils/mapChart";
......
<template>
<div class="page-box">
<div class="page-top">
<div class="head-box">
<div class="head-icon">
<img :src="codeInfo.sortImageUrl" alt="" />
</div>
<div class="head-info">
<div class="head-name one-line-ellipsis">{{ baseInfo.SEARCHNAME }}</div>
<div class="head-text">{{ baseInfo.SEARCHDATE }}</div>
</div>
<div :class="`item-tag tag-${codeInfo.sortCode}`">{{ codeInfo.sortName }}</div>
</div>
</div>
<div class="page-down">
<div class="report-box">
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, reactive } from "vue";
import { getSurvyInfo, getSearchBlurb, getOriginalUrl } from "@/api/marketAccessRestrictions/index.js"
import { useRoute } from "vue-router";
const route = useRoute();
const codeInfo = reactive({
sortCode: route.query.id,
sortName: "",
sortImageUrl: "",
})
const onSurvyInfo = async () => {
const res = await getSurvyInfo({sortCode: route.query.id})
console.log("调查分类信息", res)
if (res.code == 200) {
Object.assign(codeInfo, res.data)
}
}
const baseInfo = reactive({
SEARCHNAME: "调查详情",
SEARCHDATE: "",
})
const onSearchBlurb = async () => {
const res = await getSearchBlurb({sortCode: route.query.id, searchId: route.query.searchId})
console.log("调查简介", res)
if (res.code == 200) {
baseInfo.SEARCHNAME = res.data.SEARCHNAME
baseInfo.SEARCHDATE = res.data.SEARCHDATE
}
document.title = baseInfo.SEARCHNAME;
}
onMounted(() => {
onSurvyInfo()
onSearchBlurb()
getOriginalUrl({id: 232})
});
</script>
<style lang="scss" scoped>
.page-box {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
background: white;
.page-top {
width: 1600px;
margin: 0 auto;
box-sizing: border-box;
.head-box {
width: 100%;
display: flex;
padding: 30px 0 20px;
.head-icon {
width: 54px;
height: 54px;
font-size: 0px;
margin-right: 16px;
img {
width: 100%;
height: 100%;
}
}
.head-info {
width: 20px;
flex: auto;
.head-name {
width: 100%;
height: 26px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: bold;
line-height: 26px;
}
.head-text {
margin-top: 4px;
width: 100%;
height: 24px;
color: rgba(95, 101, 108, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
}
.item-tag {
height: 24px;
line-height: 24px;
padding: 0 8px;
border-radius: 4px;
font-weight: bold;
font-size: 16px;
letter-spacing: 2px;
}
.tag-337 {
border: 1px solid #91caff;
background: #e6f4ff;
color: #055fc2;
}
.tag-232 {
border: 1px solid #b37feb;
background: #f9f0ff;
color: #722ed1;
}
.tag-301 {
border: 1px solid #ffd591;
background: #fff7e6;
color: #fa8c16;
}
.head-button {
margin-left: 100px;
width: 120px;
height: 36px;
border-radius: 6px;
background: var(--color-main-active);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
.button-icon {
width: 16px;
height: 16px;
font-size: 0;
img {
width: 100%;
height: 100%;
}
}
.button-text {
margin-left: 8px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
}
}
}
}
.page-down {
border-top: 1px solid rgba(230, 231, 232, 1);
background-color: #f7f8f9;
width: 100%;
height: 20px;
flex: auto;
.report-box {
width: 1600px;
height: 100%;
background-color: white;
margin: 0 auto;
}
}
}
</style>
\ No newline at end of file
......@@ -14,18 +14,11 @@
</div>
<div class="box-content">
<div class="filter-row">
<el-select v-model="selectedArea" placeholder="全部领域" class="area-select" clearable @change="fetchEnterpriseList">
<el-select v-model="selectedArea" placeholder="全部领域" class="area-select" clearable @change="onEnterpriseList()">
<el-option label="全部领域" value="" />
<el-option v-for="item in areaOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input
v-model="searchText"
placeholder="搜索实体"
class="search-input"
:suffix-icon="Search"
clearable
@input="handleSearchInput"
/>
<el-input v-model="searchText" placeholder="搜索实体" class="search-input" :suffix-icon="Search" clearable @keyup.enter="onEnterpriseList()" />
</div>
<div class="enterprise-list" v-loading="listLoading">
<div class="list-label">企业名称</div>
......@@ -179,7 +172,7 @@ const businessLabels = ref([]);
const businessData = ref([]);
// 获取企业列表
const fetchEnterpriseList = async () => {
const onEnterpriseList = async () => {
listLoading.value = true;
try {
const params = {
......@@ -278,14 +271,6 @@ const updateBusinessChart = () => {
}
};
let searchTimer = null;
const handleSearchInput = () => {
if (searchTimer) clearTimeout(searchTimer);
searchTimer = setTimeout(() => {
fetchEnterpriseList();
}, 500);
};
const handleEnterpriseClick = (item, index) => {
activeIndex.value = index;
if (item.ORGID) {
......@@ -432,7 +417,7 @@ const handleBusinessToggle = (type) => {
};
onMounted(() => {
fetchEnterpriseList();
onEnterpriseList();
nextTick(() => {
initCharts();
window.addEventListener('resize', () => {
......@@ -571,6 +556,9 @@ onMounted(() => {
.search-input {
flex: auto;
width: 20px;
background-color: #fff;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 4px;
}
}
......
......@@ -12,15 +12,19 @@
<div :class="`item-tag tag-${codeInfo.sortCode}`">{{ codeInfo.sortName }}</div>
</div>
<div class="page-tabs">
<div :class="['tab-item', {'tab-active': activeName==item.name}]" v-for="(item, index) in tabList" :key="index" @click="handleClickBtn(item)">
<div :class="['tab-item', {'tab-active': activeName==1}]" @click="handleClickBtn(1)">
<div class="icon">
<img :src="item.activeIcon" alt="" v-if="activeName==item.name" />
<img :src="item.icon" alt="" v-else />
<img :src="activeName==2 ? NavIcon1Active : NavIcon1" alt="" />
</div>
<div class="text" :class="{ textActive: activeName==item.name }">
{{ item.name }}
<div class="text" :class="{ textActive: activeName==1 }">调查概况</div>
</div>
<div :class="['tab-item', {'tab-active': activeName==2}]" @click="handleClickBtn(2)" v-if="codeInfo.sortCode==337 || codeInfo.sortCode==232">
<div class="icon">
<img :src="activeName==2 ? NavIcon3Active : NavIcon3" alt="" />
</div>
<div class="text" :class="{ textActive: activeName==2 }">{{ codeInfo.sortCode==337 ? '影响分析' : '报告解析' }}</div>
</div>
<div style="width:20px; flex:auto;"></div>
<div class="head-button">
<div class="button-icon">
......@@ -48,26 +52,12 @@ import { getSurvyInfo, getSearchBlurb } from "@/api/marketAccessRestrictions/ind
import { useRoute } from "vue-router";
const route = useRoute();
const tabList = ref([
{
name: "调查概况",
icon: NavIcon1,
activeIcon: NavIcon1Active,
path: "/marketSingleCaseLayout/overview"
},
{
name: "影响分析",
icon: NavIcon3,
activeIcon: NavIcon3Active,
path: "/marketSingleCaseLayout/deepdig"
}
]);
const activeName = ref("调查案件");
const handleClickBtn = item => {
activeName.value = item.name;
const activeName = ref(1);
const handleClickBtn = index => {
activeName.value = index;
router.push({
path: item.path,
path: ['', "/marketSingleCaseLayout/overview", "/marketSingleCaseLayout/deepdig"][index],
query: { ...route.query }
});
};
......@@ -102,10 +92,10 @@ const onSearchBlurb = async () => {
onMounted(() => {
onSurvyInfo()
onSearchBlurb()
if (route.path === "/marketSingleCaseLayout/deepdig") {
activeName.value = "影响分析";
if (route.path === "/marketSingleCaseLayout/overview") {
activeName.value = 1;
} else {
activeName.value = "调查概况";
activeName.value = 2;
}
});
</script>
......
......@@ -113,20 +113,16 @@ const tips = "美国 232 调查认定,钕铁硼永磁体(关键领域核心
const route = useRoute();
const loading = ref(false);
const box2Loading = ref(false);
const box3Loading = ref(false);
const baseInfo = ref({});
const reasonList = ref([]);
const timeLineList = ref([]);
const surveyResult = ref([]);
const handleGetSearchBlurb = async () => {
loading.value = true;
try {
const res = await getSearchBlurb({
searchId: route.query.searchId,
sortCode: "232"
});
const res = await getSearchBlurb({ searchId: route.query.searchId, sortCode: "232" });
console.log('获取基本信息', res)
if (res.code === 200 && res.data) {
const data = res.data;
baseInfo.value = data;
......@@ -139,42 +135,42 @@ const handleGetSearchBlurb = async () => {
}
}
} catch (error) {
console.error("获取调查详情失败", error);
} finally {
loading.value = false;
console.error("获取基本信息失败", error);
}
loading.value = false;
};
const handleGetSearchContext = async () => {
box2Loading.value = true;
try {
const res = await getSearchContext({
searchId: route.query.searchId
});
if (res.code === 200 && res.data) {
timeLineList.value = res.data.map(item => ({
time: item.CONTTIME,
content: item.CONTDESC
}));
}
} catch (error) {
console.error("获取事件脉络失败", error);
} finally {
box2Loading.value = false;
}
};
// const box2Loading = ref(false);
// const timeLineList = ref([]);
// const handleGetSearchContext = async () => {
// box2Loading.value = true;
// try {
// const res = await getSearchContext({
// searchId: route.query.searchId
// });
// if (res.code === 200 && res.data) {
// timeLineList.value = res.data.map(item => ({
// time: item.CONTTIME,
// content: item.CONTDESC
// }));
// }
// } catch (error) {
// console.error("获取事件脉络失败", error);
// } finally {
// box2Loading.value = false;
// }
// };
const handleGetSearchConclusion = async () => {
box3Loading.value = true;
try {
const res = await getSearchConclusion({
searchId: route.query.searchId
});
const res = await getSearchConclusion({ searchId: route.query.searchId });
console.log('获取调查结论', res)
if (res.code === 200) {
surveyResult.value = res.data.map(item => {
return {
title: item.TITLE,
data: item.CONTENT?.split(/\r\n|\n/).filter(line => line.trim()) || [],
data: item.CONTENT || [],
};
});
}
......@@ -189,9 +185,8 @@ const handleGetSearchConclusion = async () => {
const eventList = ref([])
const handleGetRelatedEvents = async () => {
try {
const res = await getRelatedEvents({
searchId: route.query.searchId
});
const res = await getRelatedEvents({ searchId: route.query.searchId });
console.log('获取相关行政举措', res)
if(res.code === 200) eventList.value = res.data || [];
} catch (error) {
console.error("获取相关行政举措失败", error);
......@@ -201,7 +196,7 @@ const handleGetRelatedEvents = async () => {
onMounted(() => {
handleGetSearchBlurb();
handleGetRelatedEvents();
handleGetSearchContext();
// handleGetSearchContext();
handleGetSearchConclusion();
});
</script>
......
// 数字转中文(支持 0-99 整数)
export const onNumToChinese = (num:any) => {
// 1. 基础校验:只处理 0-99 的整数
if (!Number.isInteger(num) || num < 0 || num > 99) return '100';
// 2. 定义基础字符
const singleChars = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
const tenChar = '十';
// 3. 核心转换逻辑
if (num < 10) {
// 0-9 直接返回对应字符
return singleChars[num];
} else if (num === 10) {
// 10 特殊处理
return tenChar;
} else if (num < 20) {
// 11-19:十 + 个位(如十一、十九)
return tenChar + singleChars[num - 10];
} else {
// 20-99:十位 + 十 + 个位(个位为0则省略,如二十、二十九)
const ten = Math.floor(num / 10); // 十位数字
const unit = num % 10; // 个位数字
return singleChars[ten] + tenChar + (unit === 0 ? '' : singleChars[unit]);
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论