|
|
@ -1,18 +1,19 @@
|
|
|
|
<script setup lang="ts">
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { useRouter } from "vue-router";
|
|
|
|
|
|
|
|
import { reactive, ref, onMounted } from "vue";
|
|
|
|
import { reactive, ref, onMounted } from "vue";
|
|
|
|
import cheackImg from "@/assets/svg/live/check.svg";
|
|
|
|
import cheackImg from "@/assets/svg/live/check.svg";
|
|
|
|
import starImg from "@/assets/svg/live/star.svg";
|
|
|
|
import starImg from "@/assets/svg/live/star.svg";
|
|
|
|
import plusImg from "@/assets/svg/live/plus.svg";
|
|
|
|
import plusImg from "@/assets/svg/live/plus.svg";
|
|
|
|
import emptyImg from "@/assets/live/empty.png";
|
|
|
|
import emptyImg from "@/assets/live/empty.png";
|
|
|
|
|
|
|
|
import picEmptyImg from "@/assets/live/goods_empty.png";
|
|
|
|
import tipsImg from "@/assets/svg/live/tips.svg";
|
|
|
|
import tipsImg from "@/assets/svg/live/tips.svg";
|
|
|
|
import { FormInstance } from "element-plus/es/components";
|
|
|
|
import { FormInstance, UploadProps } from "element-plus/es/components";
|
|
|
|
import { getSalespitch } from "@/api/chat";
|
|
|
|
import { getSalespitch } from "@/api/chat";
|
|
|
|
import { Delete } from "@element-plus/icons-vue";
|
|
|
|
import { Delete, Plus } from "@element-plus/icons-vue";
|
|
|
|
const ruleFormRef = ref<FormInstance>();
|
|
|
|
const ruleFormRef = ref<FormInstance>();
|
|
|
|
const salespitchList = ref([]);
|
|
|
|
const salespitchList = ref([]);
|
|
|
|
import { message } from "@/utils/message";
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
|
|
import { message } from "@/utils/message";
|
|
|
|
|
|
|
|
import { useRouter } from "vue-router";
|
|
|
|
const formData = reactive({
|
|
|
|
const formData = reactive({
|
|
|
|
productName: "",
|
|
|
|
productName: "",
|
|
|
|
detail: "",
|
|
|
|
detail: "",
|
|
|
@ -25,6 +26,11 @@ const formData = reactive({
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
]
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const imageUrl = ref<any>("");
|
|
|
|
|
|
|
|
const goodsList = ref([]);
|
|
|
|
|
|
|
|
const activedIndex = ref(0);
|
|
|
|
|
|
|
|
const activeText = ref("");
|
|
|
|
|
|
|
|
const addFlag = ref(false);
|
|
|
|
// 验证规格和价格必填
|
|
|
|
// 验证规格和价格必填
|
|
|
|
const validateSpecifications = (rule, value, callback) => {
|
|
|
|
const validateSpecifications = (rule, value, callback) => {
|
|
|
|
// 检查是否至少有一个规格项
|
|
|
|
// 检查是否至少有一个规格项
|
|
|
@ -58,7 +64,21 @@ const rules = {
|
|
|
|
specifications: [{ required: true, validator: validateSpecifications }],
|
|
|
|
specifications: [{ required: true, validator: validateSpecifications }],
|
|
|
|
detail: [{ required: true, message: "请输入商品详情", trigger: "change" }]
|
|
|
|
detail: [{ required: true, message: "请输入商品详情", trigger: "change" }]
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleFileChange = file => {
|
|
|
|
|
|
|
|
// 验证文件大小(不超过5MB)
|
|
|
|
|
|
|
|
if (file.size > 5 * 1024 * 1024) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 读取文件并转换为Base64
|
|
|
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
|
|
|
reader.readAsDataURL(file.raw);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reader.onload = e => {
|
|
|
|
|
|
|
|
// 显示预览
|
|
|
|
|
|
|
|
imageUrl.value = e.target.result;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
const handlePriceInput = item => {
|
|
|
|
const handlePriceInput = item => {
|
|
|
|
item.price = item.price
|
|
|
|
item.price = item.price
|
|
|
|
.replace(/[^\d.]/g, "")
|
|
|
|
.replace(/[^\d.]/g, "")
|
|
|
@ -73,10 +93,36 @@ const addNorms = () => {
|
|
|
|
price: ""
|
|
|
|
price: ""
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|
|
|
|
const save = () => {
|
|
|
|
const selectIndex = index => {
|
|
|
|
if (!ruleFormRef.value) return;
|
|
|
|
activedIndex.value = index;
|
|
|
|
|
|
|
|
activeText.value = salespitchList.value[index].message;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
// 暴露方法:先保存再跳转
|
|
|
|
|
|
|
|
defineExpose({
|
|
|
|
|
|
|
|
enterLiveRoom: async () => {
|
|
|
|
|
|
|
|
// 等待保存完成,只有保存成功才跳转
|
|
|
|
|
|
|
|
const saveSuccess = await save();
|
|
|
|
|
|
|
|
if (saveSuccess) {
|
|
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
|
|
path: "/Live",
|
|
|
|
|
|
|
|
query: { gender: router.currentRoute.value.query.gender }
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 修改save为异步函数,返回保存是否成功的Promise
|
|
|
|
|
|
|
|
const save = (): Promise<boolean> => {
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
|
|
|
|
if (!ruleFormRef.value) {
|
|
|
|
|
|
|
|
resolve(false);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 表单验证
|
|
|
|
ruleFormRef.value.validate(valid => {
|
|
|
|
ruleFormRef.value.validate(valid => {
|
|
|
|
if (valid) {
|
|
|
|
if (valid) {
|
|
|
|
|
|
|
|
// 执行保存操作(假设electronAPI方法是同步的,若异步需用await)
|
|
|
|
window.electronAPI.updateConfig(
|
|
|
|
window.electronAPI.updateConfig(
|
|
|
|
"live_config",
|
|
|
|
"live_config",
|
|
|
|
"product_name",
|
|
|
|
"product_name",
|
|
|
@ -93,6 +139,18 @@ const save = () => {
|
|
|
|
formData.detail
|
|
|
|
formData.detail
|
|
|
|
);
|
|
|
|
);
|
|
|
|
message("商品信息已保存", { type: "success" });
|
|
|
|
message("商品信息已保存", { type: "success" });
|
|
|
|
|
|
|
|
resolve(true); // 保存成功
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
message("请填写完整信息", { type: "warning" });
|
|
|
|
|
|
|
|
resolve(false); // 保存失败
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const addNext = () => {
|
|
|
|
|
|
|
|
// 表单验证
|
|
|
|
|
|
|
|
ruleFormRef.value.validate(valid => {
|
|
|
|
|
|
|
|
if (valid) {
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
message("请填写完整信息", { type: "warning" });
|
|
|
|
message("请填写完整信息", { type: "warning" });
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -110,6 +168,8 @@ const generateScript = async () => {
|
|
|
|
buttonText.value = "生成AI话术";
|
|
|
|
buttonText.value = "生成AI话术";
|
|
|
|
if (res.code === 200) {
|
|
|
|
if (res.code === 200) {
|
|
|
|
salespitchList.value = res.data;
|
|
|
|
salespitchList.value = res.data;
|
|
|
|
|
|
|
|
activedIndex.value = 0;
|
|
|
|
|
|
|
|
activeText.value = salespitchList.value[0];
|
|
|
|
message("生成成功!", { type: "success", showClose: true });
|
|
|
|
message("生成成功!", { type: "success", showClose: true });
|
|
|
|
await window.electronAPI.clearSystemMessages();
|
|
|
|
await window.electronAPI.clearSystemMessages();
|
|
|
|
window.electronAPI.bulkInsertSystemMessages(res.data);
|
|
|
|
window.electronAPI.bulkInsertSystemMessages(res.data);
|
|
|
@ -146,34 +206,88 @@ onMounted(async () => {
|
|
|
|
const res = await window.electronAPI.getAllSystemMessages();
|
|
|
|
const res = await window.electronAPI.getAllSystemMessages();
|
|
|
|
if (res && Array.isArray(res)) {
|
|
|
|
if (res && Array.isArray(res)) {
|
|
|
|
salespitchList.value = res;
|
|
|
|
salespitchList.value = res;
|
|
|
|
|
|
|
|
activedIndex.value = 0;
|
|
|
|
|
|
|
|
activeText.value = salespitchList.value[0].message;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<template>
|
|
|
|
<div class="GoodsManage">
|
|
|
|
<div class="GoodsManage">
|
|
|
|
|
|
|
|
<!-- <div class="goods-list">
|
|
|
|
|
|
|
|
<div class="goods-title">
|
|
|
|
|
|
|
|
<span>商品图片</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-if="goodsList.length > 0" class="goods-pic-list">
|
|
|
|
|
|
|
|
<div v-for="(item, index) in goodsList" :key="index">
|
|
|
|
|
|
|
|
<img :src="item.url" alt="" />
|
|
|
|
|
|
|
|
<el-icon
|
|
|
|
|
|
|
|
role="img"
|
|
|
|
|
|
|
|
style="
|
|
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
|
|
color: rgba(234, 42, 42, 1);
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
"
|
|
|
|
|
|
|
|
><Delete
|
|
|
|
|
|
|
|
/></el-icon>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else class="goods-empty">
|
|
|
|
|
|
|
|
<img :src="picEmptyImg" alt="" />
|
|
|
|
|
|
|
|
<span>暂无商品图~</span>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div> -->
|
|
|
|
<div class="ai-script">
|
|
|
|
<div class="ai-script">
|
|
|
|
<div class="script-title">
|
|
|
|
<div class="script-title">
|
|
|
|
<starImg />
|
|
|
|
<starImg />
|
|
|
|
<span class="name">AI直播讲品话术</span>
|
|
|
|
<span class="name">AI直播讲品话术</span>
|
|
|
|
<cheackImg />
|
|
|
|
<cheackImg v-if="!loading" />
|
|
|
|
<span class="desc">生成/修改内容将自动保存</span>
|
|
|
|
<div v-if="loading" class="loading" v-loading="loading" />
|
|
|
|
|
|
|
|
<span class="desc" v-if="!loading && salespitchList.length === 0"
|
|
|
|
|
|
|
|
>生成/修改内容将自动保存</span
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<span class="desc" v-if="!loading && salespitchList.length > 0"
|
|
|
|
|
|
|
|
>自动保存成功</span
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<span class="desc" v-if="loading">正在保存...</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div v-if="salespitchList.length === 0" class="script-empty">
|
|
|
|
<div class="loading-text" v-loading="loading" v-if="loading" />
|
|
|
|
|
|
|
|
<div v-if="salespitchList.length === 0 && !loading" class="script-empty">
|
|
|
|
<img :src="emptyImg" alt="" />
|
|
|
|
<img :src="emptyImg" alt="" />
|
|
|
|
<span>暂无AI讲品话术~</span>
|
|
|
|
<span>暂无AI讲品话术~</span>
|
|
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
|
|
style="margin-top: 16px"
|
|
|
|
|
|
|
|
:loading="loading"
|
|
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
|
|
@click="generateScript"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
{{ buttonText }}</el-button
|
|
|
|
|
|
|
|
>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div v-else class="script-content">
|
|
|
|
<div v-if="salespitchList.length > 0 && !loading" class="script-content">
|
|
|
|
<div class="tip">
|
|
|
|
<div class="tip">
|
|
|
|
<tipsImg />
|
|
|
|
<tipsImg />
|
|
|
|
<span>以下内容由AI自动生成</span>
|
|
|
|
<span>以下内容由AI自动生成</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<!-- <div class="script-tabs">
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
|
|
|
@click="selectIndex(index)"
|
|
|
|
|
|
|
|
class="script-tabs-item"
|
|
|
|
|
|
|
|
:class="[index === activedIndex ? 'active' : '']"
|
|
|
|
|
|
|
|
v-for="(item, index) in salespitchList"
|
|
|
|
|
|
|
|
:key="item"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
{{ index + 1 }}
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
</div> -->
|
|
|
|
|
|
|
|
<!-- <div class="speech-item">{{ activeText }}</div> -->
|
|
|
|
<div
|
|
|
|
<div
|
|
|
|
v-for="(item, index) in salespitchList"
|
|
|
|
v-for="(item, index) in salespitchList"
|
|
|
|
:key="index"
|
|
|
|
:key="index"
|
|
|
|
class="speech-item"
|
|
|
|
class="speech-item"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
{{ item }}
|
|
|
|
<span>{{ item.message }}</span>
|
|
|
|
|
|
|
|
<span class="type">{{ item.type }}</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
@ -203,7 +317,7 @@ onMounted(async () => {
|
|
|
|
class="norms-item"
|
|
|
|
class="norms-item"
|
|
|
|
size="large"
|
|
|
|
size="large"
|
|
|
|
v-model="item.size"
|
|
|
|
v-model="item.size"
|
|
|
|
maxlength="20"
|
|
|
|
maxlength="100"
|
|
|
|
show-word-limit
|
|
|
|
show-word-limit
|
|
|
|
placeholder="请输入商品规格"
|
|
|
|
placeholder="请输入商品规格"
|
|
|
|
/>
|
|
|
|
/>
|
|
|
@ -215,7 +329,8 @@ onMounted(async () => {
|
|
|
|
show-word-limit
|
|
|
|
show-word-limit
|
|
|
|
placeholder="请输入商品价格"
|
|
|
|
placeholder="请输入商品价格"
|
|
|
|
@input="handlePriceInput(item)"
|
|
|
|
@input="handlePriceInput(item)"
|
|
|
|
/>
|
|
|
|
><template #append>¥</template></el-input
|
|
|
|
|
|
|
|
>
|
|
|
|
<el-icon
|
|
|
|
<el-icon
|
|
|
|
v-show="index === formData.specifications.length - 1"
|
|
|
|
v-show="index === formData.specifications.length - 1"
|
|
|
|
@click="formData.specifications.splice(index, 1)"
|
|
|
|
@click="formData.specifications.splice(index, 1)"
|
|
|
@ -233,6 +348,19 @@ onMounted(async () => {
|
|
|
|
<plusImg />
|
|
|
|
<plusImg />
|
|
|
|
<span>添加规格</span>
|
|
|
|
<span>添加规格</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<!-- <el-form-item label="商品图片" prop="productImg">
|
|
|
|
|
|
|
|
<el-upload
|
|
|
|
|
|
|
|
class="avatar-uploader"
|
|
|
|
|
|
|
|
action="#"
|
|
|
|
|
|
|
|
:show-file-list="false"
|
|
|
|
|
|
|
|
:on-change="handleFileChange"
|
|
|
|
|
|
|
|
accept="image/*"
|
|
|
|
|
|
|
|
:limit="1"
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
|
|
|
|
|
|
|
|
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
|
|
|
|
|
|
|
</el-upload>
|
|
|
|
|
|
|
|
</el-form-item> -->
|
|
|
|
<el-form-item label="商品详情" prop="detail">
|
|
|
|
<el-form-item label="商品详情" prop="detail">
|
|
|
|
<el-input
|
|
|
|
<el-input
|
|
|
|
:rows="8"
|
|
|
|
:rows="8"
|
|
|
@ -261,10 +389,14 @@ onMounted(async () => {
|
|
|
|
<el-button class="reset" @click="ruleFormRef.resetFields()"
|
|
|
|
<el-button class="reset" @click="ruleFormRef.resetFields()"
|
|
|
|
>重置</el-button
|
|
|
|
>重置</el-button
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<el-button :loading="loading" type="primary" @click="generateScript">
|
|
|
|
<!-- <el-button :loading="loading" type="primary" @click="generateScript">
|
|
|
|
{{ buttonText }}</el-button
|
|
|
|
{{ buttonText }}</el-button
|
|
|
|
|
|
|
|
> -->
|
|
|
|
|
|
|
|
<el-button type="primary" @click="save">保存当前</el-button>
|
|
|
|
|
|
|
|
<!-- <el-button v-if="addFlag" type="primary" @click="addNext"
|
|
|
|
|
|
|
|
>新建下一个</el-button
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<el-button type="primary" @click="save"> 保存</el-button>
|
|
|
|
<div class="add_btn" v-if="!addFlag">新建下一个</div> -->
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</el-form>
|
|
|
|
</el-form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
@ -276,14 +408,53 @@ onMounted(async () => {
|
|
|
|
flex: 1;
|
|
|
|
flex: 1;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: row-reverse;
|
|
|
|
flex-direction: row-reverse;
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
|
|
box-shadow: 0px 4px 8px 0px rgba(46, 128, 250, 0.1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
box-shadow: 0px 4px 8px 0px rgba(46, 128, 250, 0.1);
|
|
|
|
|
|
|
|
.goods-list {
|
|
|
|
|
|
|
|
width: 180px;
|
|
|
|
|
|
|
|
margin-left: 16px;
|
|
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
|
|
|
|
border-radius: 8px 8px 8px 8px;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
.goods-title {
|
|
|
|
|
|
|
|
height: 54px;
|
|
|
|
|
|
|
|
border-bottom: 1px solid rgba(46, 128, 250, 0.1);
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
padding-left: 16px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.goods-empty {
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
|
|
color: #86909c;
|
|
|
|
|
|
|
|
img {
|
|
|
|
|
|
|
|
width: 132px;
|
|
|
|
|
|
|
|
height: 81px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.goods-pic-list {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
img {
|
|
|
|
|
|
|
|
width: 120px;
|
|
|
|
|
|
|
|
height: 120px;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
.ai-script {
|
|
|
|
.ai-script {
|
|
|
|
width: 453px;
|
|
|
|
width: 453px;
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
flex-direction: column;
|
|
|
|
border-left: 1px solid rgba(46, 128, 250, 0.1);
|
|
|
|
border-left: 1px solid rgba(46, 128, 250, 0.1);
|
|
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
.script-title {
|
|
|
|
.script-title {
|
|
|
|
height: 54px;
|
|
|
|
height: 54px;
|
|
|
|
border-bottom: 1px solid rgba(46, 128, 250, 0.1);
|
|
|
|
border-bottom: 1px solid rgba(46, 128, 250, 0.1);
|
|
|
@ -303,6 +474,21 @@ onMounted(async () => {
|
|
|
|
color: #86909c;
|
|
|
|
color: #86909c;
|
|
|
|
margin-left: 4px;
|
|
|
|
margin-left: 4px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.loading {
|
|
|
|
|
|
|
|
width: 16px;
|
|
|
|
|
|
|
|
height: 16px;
|
|
|
|
|
|
|
|
/* 局部修改:穿透 scoped 样式 */
|
|
|
|
|
|
|
|
::v-deep .el-loading-spinner .circular {
|
|
|
|
|
|
|
|
width: 16px !important;
|
|
|
|
|
|
|
|
height: 16px !important;
|
|
|
|
|
|
|
|
top: 10px;
|
|
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-loading-spinner .circular path {
|
|
|
|
|
|
|
|
stroke: rgba(134, 144, 156, 1) !important;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.script-content {
|
|
|
|
.script-content {
|
|
|
|
padding: 16px;
|
|
|
|
padding: 16px;
|
|
|
@ -319,6 +505,24 @@ onMounted(async () => {
|
|
|
|
margin-left: 8px;
|
|
|
|
margin-left: 8px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.script-tabs {
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
border-bottom: 1px solid #e7e7e7;
|
|
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
|
|
.script-tabs-item {
|
|
|
|
|
|
|
|
width: 32px;
|
|
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
line-height: 40px;
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
color: rgba(0, 0, 0, 0.6);
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
.active {
|
|
|
|
|
|
|
|
color: #0052d9;
|
|
|
|
|
|
|
|
border-bottom: 3px solid #0052d9;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
.speech-item {
|
|
|
|
.speech-item {
|
|
|
|
font-weight: 500;
|
|
|
|
font-weight: 500;
|
|
|
|
font-size: 14px;
|
|
|
|
font-size: 14px;
|
|
|
@ -327,6 +531,23 @@ onMounted(async () => {
|
|
|
|
border-radius: 4px 4px 4px 4px;
|
|
|
|
border-radius: 4px 4px 4px 4px;
|
|
|
|
padding: 8px 12px;
|
|
|
|
padding: 8px 12px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
padding-bottom: 36px;
|
|
|
|
|
|
|
|
.type {
|
|
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
|
|
bottom: 8px;
|
|
|
|
|
|
|
|
right: 12px;
|
|
|
|
|
|
|
|
width: 96px;
|
|
|
|
|
|
|
|
height: 24px;
|
|
|
|
|
|
|
|
border-radius: 2px 2px 2px 2px;
|
|
|
|
|
|
|
|
border: 1px solid #86909c;
|
|
|
|
|
|
|
|
font-family: PingFang SC, PingFang SC;
|
|
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
color: #1d2129;
|
|
|
|
|
|
|
|
line-height: 24px;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.script-empty {
|
|
|
|
.script-empty {
|
|
|
@ -343,11 +564,31 @@ onMounted(async () => {
|
|
|
|
height: 138px;
|
|
|
|
height: 138px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.loading-text {
|
|
|
|
|
|
|
|
height: 129px;
|
|
|
|
|
|
|
|
margin: 16px;
|
|
|
|
|
|
|
|
background: #f3f4fc !important;
|
|
|
|
|
|
|
|
border-radius: 4px 4px 4px 4px;
|
|
|
|
|
|
|
|
::v-deep(.el-loading-mask) {
|
|
|
|
|
|
|
|
background-color: unset !important;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
::v-deep(.el-loading-spinner) {
|
|
|
|
|
|
|
|
width: 30px;
|
|
|
|
|
|
|
|
top: 15%;
|
|
|
|
|
|
|
|
.circular {
|
|
|
|
|
|
|
|
width: 19px !important;
|
|
|
|
|
|
|
|
height: 19px !important;
|
|
|
|
|
|
|
|
top: 10px;
|
|
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.main-content {
|
|
|
|
.main-content {
|
|
|
|
flex: 1;
|
|
|
|
flex: 1;
|
|
|
|
padding: 16px;
|
|
|
|
padding: 16px;
|
|
|
|
position: relative;
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
background: #ffffff;
|
|
|
|
.norms-list {
|
|
|
|
.norms-list {
|
|
|
|
display: flex;
|
|
|
|
display: flex;
|
|
|
|
width: 100%;
|
|
|
|
width: 100%;
|
|
|
@ -390,13 +631,58 @@ onMounted(async () => {
|
|
|
|
position: absolute;
|
|
|
|
position: absolute;
|
|
|
|
bottom: 32px;
|
|
|
|
bottom: 32px;
|
|
|
|
right: 16px;
|
|
|
|
right: 16px;
|
|
|
|
|
|
|
|
display: flex;
|
|
|
|
.reset {
|
|
|
|
.reset {
|
|
|
|
width: 94px;
|
|
|
|
width: 94px;
|
|
|
|
height: 32px;
|
|
|
|
height: 32px;
|
|
|
|
border-radius: 4px 4px 4px 4px;
|
|
|
|
border-radius: 4px 4px 4px 4px;
|
|
|
|
border: 1px solid #2e80fa;
|
|
|
|
border: 1px solid #2e80fa;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.add_btn {
|
|
|
|
|
|
|
|
width: 94px;
|
|
|
|
|
|
|
|
height: 32px;
|
|
|
|
|
|
|
|
background: #e5e6eb;
|
|
|
|
|
|
|
|
border-radius: 4px 4px 4px 4px;
|
|
|
|
|
|
|
|
border: 1px solid #e5e6eb;
|
|
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
|
|
color: #86909c;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
line-height: 32px;
|
|
|
|
|
|
|
|
margin-left: 16px;
|
|
|
|
|
|
|
|
cursor: no-drop;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
|
|
.avatar-uploader .avatar {
|
|
|
|
|
|
|
|
width: 178px;
|
|
|
|
|
|
|
|
height: 178px;
|
|
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
|
|
.avatar-uploader .el-upload {
|
|
|
|
|
|
|
|
border: 1px dashed var(--el-border-color);
|
|
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
|
|
transition: var(--el-transition-duration-fast);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.avatar-uploader .el-upload:hover {
|
|
|
|
|
|
|
|
border-color: var(--el-color-primary);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.el-icon.avatar-uploader-icon {
|
|
|
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
|
|
|
color: #8c939d;
|
|
|
|
|
|
|
|
width: 178px;
|
|
|
|
|
|
|
|
height: 178px;
|
|
|
|
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
|