This commit is contained in:
Silent YANG 2024-01-29 16:45:34 +08:00
parent 24fff5fb5d
commit 48112e0d7e
11 changed files with 881 additions and 59 deletions

BIN
public/old_font.bin Normal file

Binary file not shown.

View file

@ -12,9 +12,19 @@ const LIST: AppRouteRecordRaw = {
order: 2,
},
children: [
{
path: 'chi',
name: 'Chi',
component: () => import('@/views/list/chi/index.vue'),
meta: {
locale: '字库写入',
requiresAuth: true,
roles: ['*'],
},
},
{
path: 'backup',
name: 'Card',
name: 'Backup',
component: () => import('@/views/list/card/index.vue'),
meta: {
locale: '备份/还原',

View file

@ -4,19 +4,31 @@
<a-row :gutter="20" align="stretch">
<a-col :span="24">
<a-card class="general-card" title="备份/还原">
<a-space>
<a-button type="primary" @click="backup">备份</a-button>
<a-button @click="restore">恢复</a-button>
<a-select v-model="state.eepromType" :style="{width:'320px'}" placeholder="选择EEPROM大小">
<a-option value="1">8KB64Kbit</a-option>
<a-option value="2">128KB1Mbit</a-option>
<a-option value="3">256KB2Mbit</a-option>
<a-option value="4">512KB4Mbit</a-option>
</a-select>
<a-button type="text" @click="checkEeprom">自动检测</a-button>
</a-space>
<a-divider />
<div id="statusArea" style="height: 20em; background-color: azure; color: silver; overflow: auto; padding: 20px" v-html="state.status"></div>
<a-tabs default-active-key="1">
<a-tab-pane key="1" title="快捷备份">
<a-space>
<a-button type="primary" @click="backupConfig">备份配置</a-button>
<a-button @click="restoreConfig">恢复配置</a-button>
<a-button type="primary" @click="backupCalibration">备份校准</a-button>
<a-button @click="restoreCalibration">恢复校准</a-button>
</a-space>
</a-tab-pane>
<a-tab-pane key="2" title="完整备份">
<a-space>
<a-button type="primary" @click="backup">备份</a-button>
<a-button @click="restore">恢复</a-button>
<a-select v-model="state.eepromType" :style="{width:'320px'}" placeholder="选择EEPROM大小">
<a-option value="1">8KB64Kbit</a-option>
<a-option value="2">128KB1Mbit</a-option>
<a-option value="3">256KB2Mbit</a-option>
<a-option value="4">512KB4Mbit</a-option>
</a-select>
<a-button type="text" @click="checkEeprom">自动检测</a-button>
</a-space>
</a-tab-pane>
</a-tabs>
<a-divider />
<div id="statusArea" style="height: 20em; background-color: azure; color: silver; overflow: auto; padding: 20px" v-html="state.status"></div>
</a-card>
</a-col>
</a-row>
@ -26,12 +38,12 @@
<script lang="ts" setup>
import { reactive, nextTick } from 'vue';
import { useAppStore } from '@/store';
import { check_eeprom, eeprom_read, eeprom_write, eeprom_reboot } from '@/utils/serial.js';
import { check_eeprom, eeprom_read, eeprom_write, eeprom_reboot, eeprom_init } from '@/utils/serial.js';
const appStore = useAppStore();
const state = reactive({
status: "点击备份按钮将生成EEPROM备份文件<br/><br/>",
status: "点击备份按钮将生成 EEPROM 备份文件<br/><br/>",
eepromType: ""
})
@ -40,6 +52,74 @@ const checkEeprom = async () => {
await check_eeprom();
}
const backupRange = async (start: any, end: any, name: any = new Date() + '_backup.bin') =>{
await eeprom_init(appStore.connectPort);
let rawEEPROM = new Uint8Array(end - start);
for (let i = start; i < end; i += 0x80) {
const data = await eeprom_read(appStore.connectPort, i);
rawEEPROM.set(data, i - start);
state.status = state.status + "备份进度:" + (((i - start) / rawEEPROM.length) * 100).toFixed(1) + "%<br/>";
nextTick(()=>{
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
})
}
state.status = state.status + "备份进度100.0%<br/>";
nextTick(()=>{
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
})
console.log(rawEEPROM);
const blob = new Blob([rawEEPROM], { type: 'application/octet-stream' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
const restoreRange = async (start: any = 0) => {
await eeprom_init(appStore.connectPort);
const input = document.createElement('input');
input.type = 'file';
input.onchange = async() => {
const blob = new Blob([input.files[0]], {type: 'application/octet-stream' });
const rawEEPROM = new Uint8Array(await blob.arrayBuffer());
for (let i = start; i < input.files[0].size + start; i += 0x80) {
await eeprom_write(appStore.connectPort, i, rawEEPROM.slice(i - start, i - start + 0x80));
state.status = state.status + "恢复进度:" + (((i - start) / input.files[0].size) * 100).toFixed(1) + "%<br/>";
nextTick(()=>{
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
})
}
state.status = state.status + "恢复进度100.0%<br/>";
await eeprom_reboot(appStore.connectPort);
};
input.click();
}
const backupConfig = async() => {
if(appStore.connectState != true){alert('请先连接手台!'); return;};
await backupRange(0, 0x1E00, 'config.bin')
}
const backupCalibration = async() => {
if(appStore.connectState != true){alert('请先连接手台!'); return;};
await backupRange(0x1E00, 0x2000, 'calibration.bin')
}
const restoreConfig = async() =>{
if(appStore.connectState != true){alert('请先连接手台!'); return;};
await restoreRange()
}
const restoreCalibration = async() =>{
if(appStore.connectState != true){alert('请先连接手台!'); return;};
await restoreRange(0x1E00)
}
const backup = async() => {
if(appStore.connectState != true){alert('请先连接手台!'); return;};
let _max = 0x2000;
@ -59,58 +139,18 @@ const backup = async() => {
default:
_max = 0x2000;
}
let rawEEPROM = new Uint8Array(_max);
for (let i = 0; i < _max; i += 0x80) {
const data = await eeprom_read(appStore.connectPort, i);
rawEEPROM.set(data, i);
state.status = state.status + "备份进度:" + ((i / _max) * 100).toFixed(1) + "%<br/>";
nextTick(()=>{
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
})
}
state.status = state.status + "备份进度100%<br/>";
nextTick(()=>{
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
})
console.log(rawEEPROM);
const blob = new Blob([rawEEPROM], { type: 'application/octet-stream' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = new Date() + '_backup.bin';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
await backupRange(0, _max)
}
const restore = async() => {
if(appStore.connectState != true){alert('请先连接手台!'); return;};
const input = document.createElement('input');
input.type = 'file';
input.onchange = async() => {
const blob = new Blob([input.files[0]], {type: 'application/octet-stream' });
const rawEEPROM = new Uint8Array(await blob.arrayBuffer());
for (let i = 0; i < input.files[0].size; i += 0x80) {
await eeprom_write(appStore.connectPort, i, rawEEPROM.slice(i, i + 0x80));
state.status = state.status + "恢复进度:" + ((i / input.files[0].size) * 100).toFixed(1) + "%<br/>";
nextTick(()=>{
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
})
}
state.status = state.status + "恢复进度100%<br/>";
eeprom_reboot(appStore.connectPort);
};
input.click();
await restoreRange()
}
</script>
<script lang="ts">
export default {
name: 'Card',
name: 'Backup',
};
</script>

View file

@ -0,0 +1,204 @@
<template>
<div class="card-wrap">
<a-card v-if="loading" :bordered="false" hoverable>
<slot name="skeleton"></slot>
</a-card>
<a-card v-else :bordered="false" hoverable>
<a-space align="start">
<a-avatar
v-if="icon"
:size="24"
style="margin-right: 8px; background-color: #626aea"
>
<icon-filter />
</a-avatar>
<a-card-meta>
<template #title>
<a-typography-text style="margin-right: 10px">
{{ title }}
</a-typography-text>
<template v-if="showTag">
<a-tag
v-if="open && isExpires === false"
size="small"
color="green"
>
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ tagText }}</span>
</a-tag>
<a-tag v-else-if="isExpires" size="small" color="red">
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ expiresTagText }}</span>
</a-tag>
</template>
</template>
<template #description>
{{ description }}
<slot></slot>
</template>
</a-card-meta>
</a-space>
<template #actions>
<a-switch v-if="actionType === 'switch'" v-model="open" />
<a-space v-else-if="actionType === 'button'">
<template v-if="isExpires">
<a-button type="outline" @click="renew">
{{ expiresText }}
</a-button>
</template>
<template v-else>
<a-button v-if="open" @click="handleToggle">
{{ closeTxt }}
</a-button>
<a-button v-else-if="!open" type="outline" @click="handleToggle">
{{ openTxt }}
</a-button>
</template>
</a-space>
<div v-else>
<a-space>
<a-button @click="toggle(false)">
{{ closeTxt }}
</a-button>
<a-button type="primary" @click="toggle(true)">
{{ openTxt }}
</a-button>
</a-space>
</div>
</template>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
actionType: {
type: String,
default: '',
},
defaultValue: {
type: Boolean,
default: false,
},
openTxt: {
type: String,
default: '',
},
closeTxt: {
type: String,
default: '',
},
expiresText: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
showTag: {
type: Boolean,
default: true,
},
tagText: {
type: String,
default: '',
},
expires: {
type: Boolean,
default: false,
},
expiresTagText: {
type: String,
default: '',
},
});
const [open, toggle] = useToggle(props.defaultValue);
const handleToggle = () => {
toggle();
};
const isExpires = ref(props.expires);
const renew = () => {
isExpires.value = false;
};
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
border-radius: 4px;
&:hover {
transform: translateY(-4px);
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
}
:deep(.arco-card) {
height: 100%;
border-radius: 4px;
.arco-card-body {
height: 100%;
.arco-space {
width: 100%;
height: 100%;
.arco-space-item {
height: 100%;
&:last-child {
flex: 1;
}
.arco-card-meta {
height: 100%;
display: flex;
flex-flow: column;
.arco-card-meta-content {
flex: 1;
.arco-card-meta-description {
margin-top: 8px;
color: rgb(var(--gray-6));
line-height: 20px;
font-size: 12px;
}
}
.arco-card-meta-footer {
margin-top: 0;
}
}
}
}
}
}
:deep(.arco-card-meta-title) {
display: flex;
align-items: center;
// To prevent the shaking
line-height: 28px;
}
:deep(.arco-skeleton-line) {
&:last-child {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
}
}
</style>

View file

@ -0,0 +1,115 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.content') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
>
<div class="card-wrap empty-wrap">
<a-card :bordered="false" hoverable>
<a-result :status="null" :title="$t('cardList.content.action')">
<template #icon>
<icon-plus style="font-size: 20px" />
</template>
</a-result>
</a-card>
</div>
</a-col>
<a-col
v-for="item in renderData"
:key="item.id"
class="list-col"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:icon="item.icon"
:open-txt="$t('cardList.content.inspection')"
:close-txt="$t('cardList.content.delete')"
:show-tag="false"
>
<a-descriptions
style="margin-top: 16px"
:data="item.data"
layout="inline-horizontal"
:column="2"
/>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line
:widths="['50%', '50%', '100%', '40%']"
:rows="4"
/>
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryInspectionList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(3).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryInspectionList,
defaultValue
);
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
&:hover {
transform: translateY(-4px);
}
:deep(.arco-card-meta-description) {
color: rgb(var(--gray-6));
.arco-descriptions-item-label-inline {
font-weight: normal;
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-descriptions-item-value-inline {
color: rgb(var(--gray-8));
}
}
}
.empty-wrap {
height: 200px;
border-radius: 4px;
:deep(.arco-card) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
.arco-result-title {
color: rgb(var(--gray-6));
}
}
}
</style>

View file

@ -0,0 +1,51 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.preset') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 140px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:tag-text="$t('cardList.preset.tag')"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%']" :rows="2" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryRulesPresetList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(6).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryRulesPresetList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -0,0 +1,57 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.service') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 162px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:expires="item.expires"
:open-txt="$t('cardList.service.open')"
:close-txt="$t('cardList.service.cancel')"
:expires-text="$t('cardList.service.renew')"
:tag-text="$t('cardList.service.tag')"
:expires-tag-text="$t('cardList.service.expiresTag')"
:icon="item.icon"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryTheServiceList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(4).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryTheServiceList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -0,0 +1,121 @@
<template>
<div class="container">
<Breadcrumb :items="['小工具', '字库写入']" />
<a-row :gutter="20" align="stretch">
<a-col :span="24">
<a-card class="general-card" title="字库写入">
<a-space>
<a-button @click="restore(1)">写入 117 字库K</a-button>
<a-button @click="restore(2)">写入 118 字库K</a-button>
<a-button @click="restore(3)">写入 118 字库H</a-button>
</a-space>
<a-divider />
<div id="statusArea" style="height: 20em; background-color: azure; color: silver; overflow: auto; padding: 20px" v-html="state.status"></div>
</a-card>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { reactive, nextTick } from 'vue';
import { useAppStore } from '@/store';
import { eeprom_write, eeprom_reboot, eeprom_init } from '@/utils/serial.js';
const appStore = useAppStore();
const state = reactive({
status: "点击写入按钮写入字库到设备<br/><br/>",
eepromType: ""
})
const restoreRange = async (start: any = 0, uint8Array: any) => {
await eeprom_init(appStore.connectPort);
for (let i = start; i < uint8Array.length + start; i += 0x80) {
await eeprom_write(appStore.connectPort, i, uint8Array.slice(i - start, i - start + 0x80));
state.status = state.status + "写入进度:" + (((i - start) / uint8Array.length) * 100).toFixed(1) + "%<br/>";
nextTick(()=>{
const textarea = document?.getElementById('statusArea');
if(textarea)textarea.scrollTop = textarea?.scrollHeight;
})
}
state.status = state.status + "写入进度100.0%<br/>";
await eeprom_reboot(appStore.connectPort);
}
const restore = async(type: any = 1) => {
if(appStore.connectState != true){alert('请先连接手台!'); return;};
state.status = state.status + "正在下载字库...<br />"
let fontPacket = undefined
switch(type){
case 1:
fontPacket = await fetch('/old_font.bin')
break
default:
alert('TODO')
return
}
const reader = fontPacket.body.getReader();
const chunks = [];
while(true) {
const {done, value} = await reader.read();
if (done) {
break;
}
chunks.push(...value)
}
const binary = new Uint8Array(chunks)
await restoreRange(0x02000, binary)
}
</script>
<script lang="ts">
export default {
name: 'Chi',
};
</script>
<style scoped lang="less">
.container {
padding: 0 20px 20px 20px;
:deep(.arco-list-content) {
overflow-x: hidden;
}
:deep(.arco-card-meta-title) {
font-size: 14px;
}
}
:deep(.arco-list-col) {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
:deep(.arco-list-item) {
width: 33%;
}
:deep(.block-title) {
margin: 0 0 12px 0;
font-size: 14px;
}
:deep(.list-wrap) {
// min-height: 140px;
.list-row {
align-items: stretch;
.list-col {
margin-bottom: 16px;
}
}
:deep(.arco-space) {
width: 100%;
.arco-space-item {
&:last-child {
flex: 1;
}
}
}
}
</style>

View file

@ -0,0 +1,19 @@
export default {
'menu.list.cardList': 'Card List',
'cardList.tab.title.all': 'All',
'cardList.tab.title.content': 'Quality Inspection',
'cardList.tab.title.service': 'The service',
'cardList.tab.title.preset': 'Rules Preset',
'cardList.searchInput.placeholder': 'Search',
'cardList.enable': 'Enable',
'cardList.disable': 'Disable',
'cardList.content.delete': 'Delete',
'cardList.content.inspection': 'Inspection',
'cardList.content.action': 'Click Create Qc Content queue',
'cardList.service.open': 'Open',
'cardList.service.cancel': 'Cancel',
'cardList.service.renew': 'Contract of service',
'cardList.service.tag': 'Opened',
'cardList.service.expiresTag': 'Expired',
'cardList.preset.tag': 'Enable',
};

View file

@ -0,0 +1,19 @@
export default {
'menu.list.cardList': '卡片列表',
'cardList.tab.title.all': '全部',
'cardList.tab.title.content': '内容质检',
'cardList.tab.title.service': '开通服务',
'cardList.tab.title.preset': '规则预置',
'cardList.searchInput.placeholder': '搜索',
// 'cardList.statistic.enable': '已启用',
// 'cardList.statistic.disable': '未启用',
'cardList.content.delete': '删除',
'cardList.content.inspection': '质检',
'cardList.content.action': '点击创建质检内容队列',
'cardList.service.open': '开通服务',
'cardList.service.cancel': '取消服务',
'cardList.service.renew': '续约服务',
'cardList.service.tag': '已开通',
'cardList.service.expiresTag': '已过期',
'cardList.preset.tag': '已启用',
};

186
src/views/list/chi/mock.ts Normal file
View file

@ -0,0 +1,186 @@
import Mock from 'mockjs';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { ServiceRecord } from '@/api/list';
const qualityInspectionList: ServiceRecord[] = [
{
id: 1,
name: 'quality',
title: '视频类-历史导入',
description: '2021-10-12 00:00:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 2,
name: 'quality',
title: '图文类-图片版权',
description: '2021-12-11 18:30:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 3,
name: 'quality',
title: '图文类-高清图片',
description: '2021-10-15 08:10:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
];
const theServiceList: ServiceRecord[] = [
{
id: 1,
icon: 'code',
title: '漏斗分析',
description:
'用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
enable: true,
actionType: 'button',
},
{
id: 2,
icon: 'edit',
title: '用户分布',
description:
'快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
enable: true,
actionType: 'button',
expires: true,
},
{
id: 3,
icon: 'user',
title: '资源分发',
description:
'移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
enable: false,
actionType: 'button',
},
{
id: 4,
icon: 'user',
title: '用户画像分析',
description:
'用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
enable: true,
actionType: 'button',
},
];
const rulesPresetList: ServiceRecord[] = [
{
id: 1,
title: '内容屏蔽规则',
description:
'用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
enable: true,
actionType: 'switch',
},
{
id: 2,
title: '内容置顶规则',
description:
'该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
enable: true,
actionType: 'switch',
},
{
id: 3,
title: '内容加权规则',
description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
enable: false,
actionType: 'switch',
},
{
id: 4,
title: '内容分发规则',
description: '内容分发时对某些内容需要固定在C端展示的位置。',
enable: true,
actionType: 'switch',
},
{
id: 5,
title: '违禁内容识别',
description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
enable: false,
actionType: 'switch',
},
{
id: 6,
title: '多语言文字符号识别',
description:
'精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
enable: false,
actionType: 'switch',
},
];
setupMock({
setup() {
// Quality Inspection
Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
return successResponseWrap(
qualityInspectionList.map((_, index) => ({
...qualityInspectionList[index % qualityInspectionList.length],
id: Mock.Random.guid(),
}))
);
});
// the service
Mock.mock(new RegExp('/api/list/the-service'), () => {
return successResponseWrap(
theServiceList.map((_, index) => ({
...theServiceList[index % theServiceList.length],
id: Mock.Random.guid(),
}))
);
});
// rules preset
Mock.mock(new RegExp('/api/list/rules-preset'), () => {
return successResponseWrap(
rulesPresetList.map((_, index) => ({
...rulesPresetList[index % rulesPresetList.length],
id: Mock.Random.guid(),
}))
);
});
},
});