| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- <template>
- <ModuleBase :type="data.type">
- <template #content>
- <!-- eslint-disable max-len -->
- <div class="character-wrapper">
- <div class="fun-type">
- <a
- v-for="{ value, label } in modelList"
- :key="value"
- :class="[data.property.model === value ? 'active' : '']"
- @click="data.property.model = value"
- >{{ label }}</a
- >
- </div>
- <div v-for="(item, index) in data.option_list" :key="index" class="content-box">
- <div class="content-item">
- <el-input
- v-model="item.content"
- maxlength="10"
- show-word-limit
- placeholder="输入汉字,@:代表图片,#:代表书写格"
- @blur="handleMindMap"
- />
- <el-button @click="identify(item, index)">识别</el-button>
- <el-button @click="handleDelete(index)">删除此条</el-button>
- </div>
- <div class="option-item">
- <template v-if="data.property.model === 'miao'">
- <span>显示本体:</span>
- <el-radio-group v-model="item.is_show_ben">
- <el-radio :label="true">是</el-radio>
- <el-radio :label="false">否</el-radio>
- </el-radio-group>
- </template>
- <template v-if="data.property.model === 'write'">
- <span>需要间距:</span>
- <el-radio-group v-model="item.is_margin">
- <el-radio :label="true">是</el-radio>
- <el-radio :label="false">否</el-radio>
- </el-radio-group>
- </template>
- <template v-if="isEnable(data.property.view_pinyin)">
- <!-- <span>共用拼音:</span>
- <el-radio-group v-model="item.is_common_pinyin">
- <el-radio :label="true">是</el-radio>
- <el-radio :label="false">否</el-radio>
- </el-radio-group> -->
- <template v-if="item.is_common_pinyin">
- <span>拼音</span>
- <el-input v-model="item.pinyin" placeholder="输入拼音" />
- </template>
- </template>
- <template v-if="isEnable(data.property.is_enable_shiyi)">
- <span>释义</span>
- <el-input v-model="item.shiyi" placeholder="输入释义" />
- </template>
- </div>
- <div v-for="(items, indexs) in item.content_list" :key="indexs" class="content-items">
- <template v-if="items">
- <label>内容:{{ items.con }} </label>
- <UploadFile
- v-if="items.type === 'img'"
- :type="data.type"
- :file-list="items.file_list"
- :file-id-list="items.file_id_list"
- :label-text="'图片'"
- :accept-file-type="acceptFileType"
- :index="index"
- :indexs="indexs"
- :limit="1"
- @updateFileList="updateFileList"
- />
- <div class="option-item">
- <template v-if="isEnable(data.property.view_pinyin) && !item.is_common_pinyin">
- <span>拼音</span>
- <el-input v-model="items.pinyin" placeholder="输入拼音" />
- </template>
- <!-- <template v-if="isEnable(data.property.is_enable_shiyi) && data.property.model === 'input'">
- <span>释义</span>
- <el-input v-model="items.shiyi" placeholder="输入释义"></el-input>
- </template> -->
- </div>
- </template>
- </div>
- </div>
- <el-button icon="el-icon-plus" style="margin: 10px 0" @click="addElement">增加一个</el-button>
- </div>
- </template>
- </ModuleBase>
- </template>
- <script>
- import ModuleMixin from '../../common/ModuleMixin';
- import { getCharacterData, modelList, getOption } from '@/views/book/courseware/data/character';
- import { GetStaticResources, TextToAudioFile } from '@/api/app';
- import cnchar from 'cnchar';
- import UploadFile from '../../base/common/UploadFile.vue';
- export default {
- name: 'CharacterPage',
- components: { UploadFile },
- mixins: [ModuleMixin],
- data() {
- return {
- data: getCharacterData(),
- modelList,
- getOption,
- acceptFileType: '.png,.jpg,.jpeg',
- };
- },
- watch: {
- // 'data.content': 'handleMindMap',
- },
- methods: {
- // 解析输入内容
- handleChangeContent() {
- if (this.data.content.trim()) {
- let contentArr = this.data.content.split('\n');
- let contentList = [];
- contentArr.forEach((item, index) => {
- if (item.trim()) {
- let content_arr = item.trim().split('');
- let content_arrs = [];
- let content_arr_strokes = [];
- content_arr.forEach((itemc) => {
- if (itemc.trim()) {
- content_arrs.push(itemc.trim());
- }
- });
- content_arrs.forEach((itemc, indexc) => {
- content_arr_strokes.push(null);
- let MethodName = 'hz_resource_manager-GetHZStrokesContent';
- let data = {
- hz: itemc,
- };
- GetStaticResources(MethodName, data).then((res) => {
- let obj = {
- hz: itemc.trim(),
- strokes: res,
- };
- content_arr_strokes[indexc] = obj;
- });
- });
- contentList.push({
- con: item.trim(),
- pinyin: cnchar.spell(item.trim(), 'array', 'low', 'tone').join(' '),
- audio_file_id: '',
- hz_strokes_list: content_arr_strokes,
- });
- this.handleMatic(item.trim(), contentList.length - 1);
- }
- });
- this.data.content_list = contentList;
- } else {
- this.data.content_list = [];
- }
- this.handleMindMap();
- },
- // 自动生成音频
- handleMatic(con, index) {
- TextToAudioFile({
- text: con.replace(/<[^>]+>/g, ''),
- })
- .then(({ status, file_id, file_url }) => {
- if (status === 1) {
- this.data.option_list[index].audio_file_id = {
- file_url,
- file_id,
- };
- }
- })
- .catch(() => {});
- },
- updateFileList({ file_list, file_id_list }, index, indexs) {
- this.data.option_list[index].content_list[indexs].file_list = file_list;
- this.data.option_list[index].content_list[indexs].file_id_list = file_id_list;
- },
- // 增加
- addElement() {
- this.data.option_list.push(getOption());
- },
- // 删除
- handleDelete(index) {
- this.data.option_list.splice(index, 1);
- },
- handleMindMap() {
- // 思维导图数据
- let node_list = [];
- this.data.option_list.forEach((item) => {
- node_list.push({
- name: item.content.replace(/<[^>]*>?/gm, ''),
- id: Math.random().toString(36).substring(2, 12),
- });
- });
- this.data.mind_map.node_list = node_list;
- },
- // 识别
- async identify(items, index) {
- let con = items.content.trim();
- if (con) {
- items.content_list = [];
- let arr = con.split('');
- const regex = /[\u4E00-\u9FFF]/;
- let str = '';
- arr.forEach((item) => {
- if (regex.test(item)) {
- str += item;
- }
- });
- let MethodName = 'hz_resource_manager-GetMultHZStrokesContent';
- let data = {
- hz_str: str,
- };
- items.pinyin = cnchar.spell(str, 'array', 'low', 'tone').join(' ');
- await GetStaticResources(MethodName, data)
- .then((res) => {
- for (let key in res) {
- if (key != 'status' && key != ',' && res[key]) {
- res[key] = JSON.parse(res[key]);
- }
- }
- let hzDetailList = res;
- arr.forEach((item, index) => {
- let objs = {};
- if (item === '@') {
- // 图片
- objs = {
- con: item,
- type: 'img',
- file_list: [],
- file_id_list: [],
- pinyin: '',
- };
- } else if (item === '#') {
- // 书写
- objs = {
- con: item,
- type: 'write',
- img: '',
- base64: '',
- pinyin: '',
- };
- } else if (regex.test(item)) {
- // 汉字
- let hz_list = [];
- let res = JSON.parse(JSON.stringify(hzDetailList[item]));
- let obj = {
- con: item,
- hzDetail: {
- hz_json: res,
- },
- };
- hz_list.push(obj);
- objs = {
- con: item,
- type: 'hanzi',
- hz_info: hz_list,
- pinyin: cnchar.spell(item, 'array', 'low', 'tone').join(' '),
- shiyi: '',
- answer: '',
- is_example: false,
- answer_pinyin: '',
- answer_en: '',
- is_can_input_answer: true,
- high_strokes: '',
- };
- } else {
- // 连字符
- objs = {
- con: item,
- type: 'lian',
- pinyin: '',
- };
- }
- this.$set(items.content_list, index, objs);
- });
- })
- .catch(() => {});
- if (str) {
- this.handleMatic(str, index);
- }
- } else {
- this.$message.warning('请先输入内容');
- }
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .character-wrapper {
- display: flex;
- flex-direction: column;
- row-gap: 16px;
- align-items: flex-start;
- :deep .rich-wrapper {
- width: 100%;
- }
- .tips {
- font-size: 12px;
- color: #999;
- }
- .fun-type {
- display: flex;
- gap: 5px;
- width: 100%;
- padding-bottom: 10px;
- border-bottom: 1px solid #e5e6eb;
- a {
- padding: 5px 10px;
- font-weight: normal;
- color: #1d2129;
- cursor: pointer;
- background: #f2f3f5;
- border: 1px solid #f2f3f5;
- border-radius: 2px;
- &.active {
- color: #165dff;
- background: #e7eeff;
- border-color: #165dff;
- }
- }
- }
- .upload-file {
- display: flex;
- column-gap: 12px;
- align-items: center;
- margin: 8px 0;
- .file-name {
- display: flex;
- column-gap: 14px;
- align-items: center;
- justify-content: space-between;
- max-width: 360px;
- padding: 8px 12px;
- font-size: 14px;
- color: #1d2129;
- background-color: #f7f8fa;
- span {
- display: flex;
- column-gap: 14px;
- align-items: center;
- }
- }
- .svg-icon {
- cursor: pointer;
- }
- }
- .fun-type {
- display: flex;
- gap: 5px;
- width: 100%;
- padding-bottom: 10px;
- border-bottom: 1px solid #e5e6eb;
- a {
- padding: 5px 10px;
- font-weight: normal;
- color: #1d2129;
- cursor: pointer;
- background: #f2f3f5;
- border: 1px solid #f2f3f5;
- border-radius: 2px;
- &.active {
- color: #165dff;
- background: #e7eeff;
- border-color: #165dff;
- }
- }
- }
- .content-box {
- width: 100%;
- }
- .content-item {
- display: flex;
- gap: 16px;
- .el-input {
- max-width: 400px;
- }
- }
- .content-items {
- margin: 10px 0;
- label {
- font-size: 14px;
- line-height: 34px;
- color: #4e5969;
- }
- }
- .option-item {
- display: flex;
- flex-flow: wrap;
- align-items: center;
- margin-top: 5px;
- span {
- flex-shrink: 0;
- width: max-content;
- margin-right: 10px;
- font-size: 14px;
- color: #4e5969;
- }
- .el-input {
- max-width: 100px;
- margin-right: 30px;
- }
- .el-radio-group {
- margin-right: 30px;
- }
- }
- }
- </style>
|