2026-01-23 15:51:26 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="common-phrases-page">
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<view class="tabs-bar">
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="tab-item"
|
|
|
|
|
|
:class="{ active: activeTab === 'mine' }"
|
|
|
|
|
|
@click="switchTab('mine')"
|
|
|
|
|
|
>
|
|
|
|
|
|
我的常用语
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view
|
|
|
|
|
|
class="tab-item"
|
|
|
|
|
|
:class="{ active: activeTab === 'more' }"
|
|
|
|
|
|
@click="switchTab('more')"
|
|
|
|
|
|
>
|
|
|
|
|
|
更多常用语
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<view class="content-wrapper">
|
|
|
|
|
|
<view class="category-sidebar">
|
|
|
|
|
|
<scroll-view class="category-list" scroll-y>
|
2026-01-23 16:41:39 +08:00
|
|
|
|
<view
|
2026-05-20 16:32:00 +08:00
|
|
|
|
v-for="category in currentCategories"
|
2026-01-23 16:09:34 +08:00
|
|
|
|
:key="category.id"
|
|
|
|
|
|
class="category-item"
|
|
|
|
|
|
:class="{ active: currentCategory === category.id }"
|
2026-01-26 18:08:01 +08:00
|
|
|
|
@click="handleCategoryClick(category)"
|
2026-01-23 16:09:34 +08:00
|
|
|
|
@longpress="handleCategoryLongPress(category)"
|
|
|
|
|
|
>
|
2026-01-23 16:41:39 +08:00
|
|
|
|
<view class="category-content">
|
|
|
|
|
|
<text class="category-name">{{ category.name }}</text>
|
|
|
|
|
|
<view
|
2026-05-20 16:32:00 +08:00
|
|
|
|
v-if="activeTab === 'mine' && isEditMode && category.deletable"
|
2026-01-23 16:41:39 +08:00
|
|
|
|
class="delete-badge"
|
|
|
|
|
|
@click.stop="deleteCategory(category)"
|
|
|
|
|
|
>
|
|
|
|
|
|
<text class="delete-icon">×</text>
|
|
|
|
|
|
</view>
|
2026-01-23 16:09:34 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-if="activeTab === 'mine'"
|
|
|
|
|
|
class="add-category-footer"
|
|
|
|
|
|
@click="showAddCategoryDialog"
|
|
|
|
|
|
>
|
2026-01-26 18:08:01 +08:00
|
|
|
|
<text class="add-category-text">新增分类</text>
|
|
|
|
|
|
</view>
|
2026-01-23 15:51:26 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<view class="phrases-container">
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<view class="list-header">
|
|
|
|
|
|
<view class="current-title">
|
|
|
|
|
|
{{ currentCategoryName }}({{ currentPhrases.length }})
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="search-box">
|
|
|
|
|
|
<text class="search-icon">⌕</text>
|
|
|
|
|
|
<input
|
|
|
|
|
|
v-model="searchKeyword"
|
|
|
|
|
|
class="search-input"
|
|
|
|
|
|
placeholder="搜索常用语"
|
|
|
|
|
|
confirm-type="search"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<text v-if="searchKeyword" class="clear-search" @click="searchKeyword = ''">×</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<scroll-view class="phrases-list" scroll-y>
|
2026-01-23 16:41:39 +08:00
|
|
|
|
<view
|
|
|
|
|
|
v-for="phrase in currentPhrases"
|
2026-01-23 16:09:34 +08:00
|
|
|
|
:key="phrase.id"
|
|
|
|
|
|
class="phrase-item"
|
|
|
|
|
|
>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<view class="phrase-top">
|
|
|
|
|
|
<view class="phrase-content">{{ phrase.content }}</view>
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-if="activeTab === 'mine' && phrase.sourceCommonWordId"
|
|
|
|
|
|
class="collected-badge"
|
|
|
|
|
|
>
|
|
|
|
|
|
已收藏
|
2026-01-23 16:09:34 +08:00
|
|
|
|
</view>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
<view class="phrase-actions">
|
|
|
|
|
|
<view class="action-btn send" @click.stop="sendPhrase(phrase)">
|
|
|
|
|
|
<text class="action-icon">✈</text>
|
|
|
|
|
|
<text>发送</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<template v-if="activeTab === 'mine'">
|
|
|
|
|
|
<view class="action-btn edit" @click.stop="editPhrase(phrase)">
|
|
|
|
|
|
<text class="action-icon">✎</text>
|
|
|
|
|
|
<text>编辑</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="action-btn delete" @click.stop="deletePhrase(phrase)">
|
|
|
|
|
|
<text class="action-icon">⌫</text>
|
|
|
|
|
|
<text>删除</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
2026-01-23 16:41:39 +08:00
|
|
|
|
<view
|
2026-05-20 16:32:00 +08:00
|
|
|
|
v-else
|
|
|
|
|
|
class="action-btn collect"
|
|
|
|
|
|
:class="{ collected: isFavorite(phrase) }"
|
|
|
|
|
|
@click.stop="toggleFavorite(phrase)"
|
2026-01-23 16:41:39 +08:00
|
|
|
|
>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<text class="action-icon">{{ isFavorite(phrase) ? "★" : "☆" }}</text>
|
|
|
|
|
|
<text>{{ isFavorite(phrase) ? "已收藏" : "收藏" }}</text>
|
2026-01-23 16:09:34 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<view v-if="currentPhrases.length === 0" class="empty-state">
|
|
|
|
|
|
<text class="empty-text">暂无常用语</text>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<text class="empty-hint">
|
|
|
|
|
|
{{ activeTab === "mine" ? "可添加快捷回复或收藏更多常用语" : "可在后台常用语库维护后使用" }}
|
|
|
|
|
|
</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view v-if="activeTab === 'more' && currentPhrases.length > 0" class="collect-tip">
|
|
|
|
|
|
收藏时请选择保存到“我的常用语”的真实目录
|
2026-01-23 16:09:34 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
|
|
|
|
|
|
<view v-if="activeTab === 'mine'" class="footer-action-bar">
|
2026-01-26 18:08:01 +08:00
|
|
|
|
<view class="add-phrase-btn" @click="showAddPhraseDialog">
|
|
|
|
|
|
<text class="add-icon">+</text>
|
|
|
|
|
|
<text class="add-text">添加快捷回复</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="edit-btn" @click="toggleEditMode">
|
|
|
|
|
|
<text class="edit-text">{{ isEditMode ? "完成" : "编辑" }}</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2026-01-23 16:09:34 +08:00
|
|
|
|
</view>
|
2026-01-23 15:51:26 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view v-if="showPhrasePopup" class="popup-mask" @click="closePopup">
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<view class="popup-content phrase-popup" @click.stop>
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<view class="popup-header">
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<text class="popup-title">{{ editingPhrase ? "编辑常用语" : "添加常用语" }}</text>
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<view class="popup-close" @click="closePopup">
|
|
|
|
|
|
<text class="close-icon">×</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
|
|
|
|
|
|
<view class="form-label">所在目录</view>
|
|
|
|
|
|
<picker
|
|
|
|
|
|
mode="selector"
|
|
|
|
|
|
:range="myCategories"
|
|
|
|
|
|
range-key="name"
|
|
|
|
|
|
:value="phraseCategoryIndex"
|
|
|
|
|
|
@change="handlePhraseCategoryChange"
|
|
|
|
|
|
>
|
|
|
|
|
|
<view class="category-picker">
|
|
|
|
|
|
<text>{{ selectedPhraseCategoryName }}</text>
|
|
|
|
|
|
<text class="picker-arrow">⌄</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</picker>
|
|
|
|
|
|
<view class="form-hint">可选择保存到指定目录</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="form-label content-label">常用语内容</view>
|
2026-01-23 16:41:39 +08:00
|
|
|
|
<textarea
|
|
|
|
|
|
v-model="phraseForm.content"
|
2026-01-23 15:51:26 +08:00
|
|
|
|
class="phrase-textarea"
|
2026-05-20 16:32:00 +08:00
|
|
|
|
placeholder="请输入常用语内容,支持换行"
|
2026-01-23 15:51:26 +08:00
|
|
|
|
maxlength="500"
|
2026-05-20 16:32:00 +08:00
|
|
|
|
:auto-height="false"
|
2026-01-23 15:51:26 +08:00
|
|
|
|
></textarea>
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<view class="char-count">{{ phraseForm.content.length }}/500</view>
|
2026-01-23 15:51:26 +08:00
|
|
|
|
<view class="popup-actions">
|
|
|
|
|
|
<button class="cancel-btn" @click="closePopup">取消</button>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<button class="confirm-btn" @click="savePhrase">保存</button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view v-if="showCollectPopup" class="popup-mask" @click="closeCollectPopup">
|
|
|
|
|
|
<view class="popup-content collect-popup" @click.stop>
|
|
|
|
|
|
<view class="popup-header">
|
|
|
|
|
|
<text class="popup-title">收藏常用语</text>
|
|
|
|
|
|
<view class="popup-close" @click="closeCollectPopup">
|
|
|
|
|
|
<text class="close-icon">×</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="form-label">保存目录</view>
|
|
|
|
|
|
<picker
|
|
|
|
|
|
mode="selector"
|
|
|
|
|
|
:range="myCategories"
|
|
|
|
|
|
range-key="name"
|
|
|
|
|
|
:value="collectCategoryIndex"
|
|
|
|
|
|
@change="handleCollectCategoryChange"
|
|
|
|
|
|
>
|
|
|
|
|
|
<view class="category-picker">
|
|
|
|
|
|
<text>{{ selectedCollectCategoryName }}</text>
|
|
|
|
|
|
<text class="picker-arrow">⌄</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</picker>
|
|
|
|
|
|
<view class="form-hint">收藏后将添加到所选目录</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="collect-preview">{{ collectingPhrase?.content || "" }}</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="popup-actions">
|
|
|
|
|
|
<button class="cancel-btn" @click="closeCollectPopup">取消</button>
|
|
|
|
|
|
<button class="confirm-btn" @click="confirmFavorite">收藏</button>
|
2026-01-23 15:51:26 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
2026-01-23 16:41:39 +08:00
|
|
|
|
<view
|
|
|
|
|
|
v-if="showCategoryPopup"
|
|
|
|
|
|
class="popup-mask"
|
|
|
|
|
|
@click="closeCategoryPopup"
|
|
|
|
|
|
>
|
2026-01-23 15:51:26 +08:00
|
|
|
|
<view class="popup-content category-popup" @click.stop>
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<view class="popup-header">
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<text class="popup-title">{{ editingCategory ? "编辑分类" : "新建分类" }}</text>
|
2026-01-23 16:09:34 +08:00
|
|
|
|
<view class="popup-close" @click="closeCategoryPopup">
|
|
|
|
|
|
<text class="close-icon">×</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2026-01-23 16:41:39 +08:00
|
|
|
|
<input
|
|
|
|
|
|
v-model="categoryForm.name"
|
2026-01-23 15:51:26 +08:00
|
|
|
|
class="category-input"
|
2026-05-20 16:32:00 +08:00
|
|
|
|
placeholder="请输入分类名,最多10个字"
|
2026-01-23 15:51:26 +08:00
|
|
|
|
/>
|
|
|
|
|
|
<view class="popup-actions">
|
|
|
|
|
|
<button class="cancel-btn" @click="closeCategoryPopup">取消</button>
|
2026-05-20 16:32:00 +08:00
|
|
|
|
<button class="confirm-btn" @click="saveCategory">保存</button>
|
2026-01-23 15:51:26 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2026-01-23 16:41:39 +08:00
|
|
|
|
import { ref, computed, onMounted } from "vue";
|
2026-01-26 18:08:01 +08:00
|
|
|
|
import { storeToRefs } from "pinia";
|
2026-01-23 16:41:39 +08:00
|
|
|
|
import api from "@/utils/api";
|
2026-01-26 18:08:01 +08:00
|
|
|
|
import useAccountStore from "@/store/account";
|
|
|
|
|
|
|
|
|
|
|
|
const { doctorInfo } = storeToRefs(useAccountStore());
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const activeTab = ref("mine");
|
2026-01-23 15:51:26 +08:00
|
|
|
|
const isEditMode = ref(false);
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const searchKeyword = ref("");
|
|
|
|
|
|
const currentCategory = ref("");
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const myCategories = ref([]);
|
|
|
|
|
|
const myPhrases = ref([]);
|
|
|
|
|
|
const corpCategories = ref([]);
|
|
|
|
|
|
const corpPhrases = ref([]);
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const showPhrasePopup = ref(false);
|
|
|
|
|
|
const showCategoryPopup = ref(false);
|
|
|
|
|
|
const showCollectPopup = ref(false);
|
|
|
|
|
|
const editingPhrase = ref(null);
|
|
|
|
|
|
const editingCategory = ref(null);
|
|
|
|
|
|
const collectingPhrase = ref(null);
|
2026-01-26 18:08:01 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const phraseForm = ref({
|
|
|
|
|
|
content: "",
|
|
|
|
|
|
cateId: "",
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const collectForm = ref({
|
|
|
|
|
|
cateId: "",
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const categoryForm = ref({
|
|
|
|
|
|
name: "",
|
|
|
|
|
|
});
|
2026-01-26 18:08:01 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const currentCategories = computed(() => {
|
|
|
|
|
|
return activeTab.value === "more" ? corpCategories.value : myCategories.value;
|
2026-01-26 18:08:01 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const currentCategoryName = computed(() => {
|
|
|
|
|
|
const category = currentCategories.value.find((item) => item.id === currentCategory.value);
|
|
|
|
|
|
return category ? category.name : "未选择";
|
|
|
|
|
|
});
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const firstMyCategory = computed(() => {
|
|
|
|
|
|
return myCategories.value[0];
|
|
|
|
|
|
});
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const favoriteMap = computed(() => {
|
|
|
|
|
|
return myPhrases.value.reduce((map, item) => {
|
|
|
|
|
|
if (item.sourceCommonWordId) map[item.sourceCommonWordId] = item;
|
|
|
|
|
|
return map;
|
|
|
|
|
|
}, {});
|
|
|
|
|
|
});
|
2026-01-26 18:08:01 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const getCategoryScopeIds = (categories, categoryId) => {
|
|
|
|
|
|
const ids = [categoryId].filter(Boolean);
|
|
|
|
|
|
let changed = true;
|
|
|
|
|
|
while (changed) {
|
|
|
|
|
|
changed = false;
|
|
|
|
|
|
categories.forEach((item) => {
|
|
|
|
|
|
if (item.parentId && ids.includes(item.parentId) && !ids.includes(item.id)) {
|
|
|
|
|
|
ids.push(item.id);
|
|
|
|
|
|
changed = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-01-26 18:08:01 +08:00
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
return ids;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const currentPhrases = computed(() => {
|
|
|
|
|
|
const keyword = searchKeyword.value.trim();
|
|
|
|
|
|
const source = activeTab.value === "more" ? corpPhrases.value : myPhrases.value;
|
|
|
|
|
|
const scopeIds = getCategoryScopeIds(currentCategories.value, currentCategory.value);
|
|
|
|
|
|
let list = source.filter((item) => scopeIds.includes(item.cateId));
|
|
|
|
|
|
|
|
|
|
|
|
if (keyword) {
|
|
|
|
|
|
list = list.filter((item) => String(item.content || "").includes(keyword));
|
2026-01-26 18:08:01 +08:00
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
|
|
|
|
|
|
return list;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const phraseCategoryIndex = computed(() => {
|
|
|
|
|
|
const index = myCategories.value.findIndex((item) => item.id === phraseForm.value.cateId);
|
|
|
|
|
|
return index > -1 ? index : 0;
|
|
|
|
|
|
});
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const selectedPhraseCategoryName = computed(() => {
|
|
|
|
|
|
return myCategories.value[phraseCategoryIndex.value]?.name || "请选择目录";
|
2026-01-23 15:51:26 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const collectCategoryIndex = computed(() => {
|
|
|
|
|
|
const index = myCategories.value.findIndex((item) => item.id === collectForm.value.cateId);
|
|
|
|
|
|
return index > -1 ? index : 0;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const selectedCollectCategoryName = computed(() => {
|
|
|
|
|
|
return myCategories.value[collectCategoryIndex.value]?.name || "请选择目录";
|
|
|
|
|
|
});
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const normalizeCategory = (item, categoryType) => ({
|
|
|
|
|
|
id: item._id || item.id,
|
|
|
|
|
|
name: item.label || item.name || "未命名",
|
|
|
|
|
|
sort: item.sort || 0,
|
|
|
|
|
|
level: item.level || 1,
|
|
|
|
|
|
parentId: item.parentId || "",
|
|
|
|
|
|
type: categoryType,
|
|
|
|
|
|
deletable: categoryType === "user",
|
|
|
|
|
|
});
|
2026-01-23 16:09:34 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const normalizePhrase = (item, phraseType) => ({
|
|
|
|
|
|
id: item._id || item.id,
|
|
|
|
|
|
cateId: item.cateId || item.categoryId,
|
|
|
|
|
|
content: item.content || "",
|
|
|
|
|
|
createTime: item.createTime,
|
|
|
|
|
|
updateTime: item.updateTime,
|
|
|
|
|
|
sourceType: item.sourceType,
|
|
|
|
|
|
sourceCommonWordId: item.sourceCommonWordId,
|
|
|
|
|
|
sourceCateId: item.sourceCateId,
|
|
|
|
|
|
collectTime: item.collectTime,
|
|
|
|
|
|
collectClient: item.collectClient,
|
|
|
|
|
|
type: phraseType,
|
|
|
|
|
|
});
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const getAccountParams = () => {
|
|
|
|
|
|
const corpId = doctorInfo.value?.corpId;
|
|
|
|
|
|
const userId = doctorInfo.value?.userid;
|
|
|
|
|
|
return { corpId, userId };
|
2026-01-23 15:51:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const isFavorite = (phrase) => Boolean(favoriteMap.value[phrase.id]);
|
|
|
|
|
|
|
|
|
|
|
|
const switchTab = (tab) => {
|
|
|
|
|
|
if (activeTab.value === tab) return;
|
|
|
|
|
|
activeTab.value = tab;
|
|
|
|
|
|
isEditMode.value = false;
|
|
|
|
|
|
searchKeyword.value = "";
|
|
|
|
|
|
currentCategory.value =
|
|
|
|
|
|
tab === "mine"
|
|
|
|
|
|
? firstMyCategory.value?.id || ""
|
|
|
|
|
|
: corpCategories.value[0]?.id || "";
|
2026-01-26 18:08:01 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const toggleEditMode = () => {
|
|
|
|
|
|
isEditMode.value = !isEditMode.value;
|
2026-01-26 18:08:01 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const handleCategoryClick = (category) => {
|
|
|
|
|
|
if (activeTab.value === "mine" && isEditMode.value && category.deletable) {
|
|
|
|
|
|
editCategory(category);
|
2026-01-23 15:51:26 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
currentCategory.value = category.id;
|
|
|
|
|
|
};
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const sendPhrase = (phrase) => {
|
2026-01-23 15:51:26 +08:00
|
|
|
|
const pages = getCurrentPages();
|
|
|
|
|
|
const prevPage = pages[pages.length - 2];
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-01-23 15:51:26 +08:00
|
|
|
|
if (prevPage) {
|
|
|
|
|
|
prevPage.$vm.sendCommonPhrase(phrase.content);
|
|
|
|
|
|
}
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-01-23 15:51:26 +08:00
|
|
|
|
uni.navigateBack();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const showAddPhraseDialog = () => {
|
|
|
|
|
|
editingPhrase.value = null;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
phraseForm.value = {
|
|
|
|
|
|
content: "",
|
|
|
|
|
|
cateId: currentCategory.value || firstMyCategory.value?.id || "",
|
|
|
|
|
|
};
|
2026-01-23 15:51:26 +08:00
|
|
|
|
showPhrasePopup.value = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const editPhrase = (phrase) => {
|
|
|
|
|
|
editingPhrase.value = phrase;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
phraseForm.value = {
|
|
|
|
|
|
content: phrase.content,
|
|
|
|
|
|
cateId: phrase.cateId || firstMyCategory.value?.id || "",
|
|
|
|
|
|
};
|
2026-01-23 15:51:26 +08:00
|
|
|
|
showPhrasePopup.value = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const handlePhraseCategoryChange = (event) => {
|
|
|
|
|
|
const index = Number(event.detail.value || 0);
|
|
|
|
|
|
phraseForm.value.cateId = myCategories.value[index]?.id || "";
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-23 15:51:26 +08:00
|
|
|
|
const savePhrase = async () => {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
if (!phraseForm.value.cateId) {
|
|
|
|
|
|
uni.showToast({ title: "请选择目录", icon: "none" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
if (!phraseForm.value.content.trim()) {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: "请输入内容", icon: "none" });
|
2026-01-23 15:51:26 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
if (!corpId || !userId) {
|
|
|
|
|
|
uni.showToast({ title: "请先登录", icon: "none" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-26 18:08:01 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
try {
|
|
|
|
|
|
const result = await api("setCommonWords", {
|
2026-01-23 16:42:50 +08:00
|
|
|
|
id: editingPhrase.value?.id,
|
2026-05-20 16:32:00 +08:00
|
|
|
|
cateId: phraseForm.value.cateId,
|
2026-01-23 16:42:50 +08:00
|
|
|
|
content: phraseForm.value.content,
|
|
|
|
|
|
corpId,
|
2026-01-26 18:08:01 +08:00
|
|
|
|
userId,
|
2026-01-23 16:42:50 +08:00
|
|
|
|
});
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-01-26 18:08:01 +08:00
|
|
|
|
if (result.success) {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const nextPhrase = normalizePhrase({
|
|
|
|
|
|
...editingPhrase.value,
|
|
|
|
|
|
...(result.data || {}),
|
|
|
|
|
|
_id: editingPhrase.value?.id || result.data?._id,
|
|
|
|
|
|
cateId: phraseForm.value.cateId,
|
|
|
|
|
|
content: phraseForm.value.content.trim(),
|
|
|
|
|
|
}, "user");
|
|
|
|
|
|
|
2026-01-23 16:42:50 +08:00
|
|
|
|
if (editingPhrase.value) {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const index = myPhrases.value.findIndex((item) => item.id === editingPhrase.value.id);
|
|
|
|
|
|
if (index > -1) myPhrases.value.splice(index, 1, nextPhrase);
|
|
|
|
|
|
} else if (nextPhrase.id) {
|
|
|
|
|
|
myPhrases.value.unshift(nextPhrase);
|
2026-01-23 15:51:26 +08:00
|
|
|
|
} else {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
await loadMyPhrases();
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: "保存成功", icon: "success" });
|
2026-01-23 16:42:50 +08:00
|
|
|
|
closePopup();
|
|
|
|
|
|
} else {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: result.message || "操作失败", icon: "none" });
|
2026-01-23 16:42:50 +08:00
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
} catch (error) {
|
2026-01-26 18:08:01 +08:00
|
|
|
|
console.error("保存常用语失败:", error);
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: "操作失败", icon: "none" });
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const removeMyPhrase = async (phrase) => {
|
|
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
const result = await api("removeCommonWords", {
|
|
|
|
|
|
id: phrase.id,
|
|
|
|
|
|
corpId,
|
|
|
|
|
|
userId,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
|
const index = myPhrases.value.findIndex((item) => item.id === phrase.id);
|
|
|
|
|
|
if (index > -1) myPhrases.value.splice(index, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-23 15:51:26 +08:00
|
|
|
|
const deletePhrase = (phrase) => {
|
|
|
|
|
|
uni.showModal({
|
2026-01-23 16:41:39 +08:00
|
|
|
|
title: "提示",
|
|
|
|
|
|
content: "确定删除该常用语吗?",
|
2026-01-23 15:51:26 +08:00
|
|
|
|
success: async (res) => {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
if (!res.confirm) return;
|
|
|
|
|
|
try {
|
|
|
|
|
|
const result = await removeMyPhrase(phrase);
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
|
uni.showToast({ title: "删除成功", icon: "success" });
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({ title: result.message || "删除失败", icon: "none" });
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("删除常用语失败:", error);
|
|
|
|
|
|
uni.showToast({ title: "删除失败", icon: "none" });
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
2026-01-23 16:41:39 +08:00
|
|
|
|
},
|
2026-01-23 15:51:26 +08:00
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const toggleFavorite = async (phrase) => {
|
|
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
if (!corpId || !userId) {
|
|
|
|
|
|
uni.showToast({ title: "请先登录", icon: "none" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const favorite = favoriteMap.value[phrase.id];
|
|
|
|
|
|
if (favorite) {
|
|
|
|
|
|
const result = await removeMyPhrase(favorite);
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
|
uni.showToast({ title: "已取消收藏", icon: "success" });
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({ title: result.message || "取消收藏失败", icon: "none" });
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (myCategories.value.length === 0) {
|
|
|
|
|
|
uni.showToast({ title: "请先新增目录", icon: "none" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
collectingPhrase.value = phrase;
|
|
|
|
|
|
collectForm.value.cateId = firstMyCategory.value?.id || "";
|
|
|
|
|
|
showCollectPopup.value = true;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("收藏操作失败:", error);
|
|
|
|
|
|
uni.showToast({ title: "操作失败", icon: "none" });
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleCollectCategoryChange = (event) => {
|
|
|
|
|
|
const index = Number(event.detail.value || 0);
|
|
|
|
|
|
collectForm.value.cateId = myCategories.value[index]?.id || "";
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const confirmFavorite = async () => {
|
|
|
|
|
|
const phrase = collectingPhrase.value;
|
|
|
|
|
|
if (!phrase) {
|
|
|
|
|
|
closeCollectPopup();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!collectForm.value.cateId) {
|
|
|
|
|
|
uni.showToast({ title: "请选择目录", icon: "none" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
if (!corpId || !userId) {
|
|
|
|
|
|
uni.showToast({ title: "请先登录", icon: "none" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const result = await api("setCommonWords", {
|
|
|
|
|
|
cateId: collectForm.value.cateId,
|
|
|
|
|
|
content: phrase.content,
|
|
|
|
|
|
corpId,
|
|
|
|
|
|
userId,
|
|
|
|
|
|
sourceType: "common-words",
|
|
|
|
|
|
sourceCommonWordId: phrase.id,
|
|
|
|
|
|
sourceCateId: phrase.cateId,
|
|
|
|
|
|
collectClient: "wxapp",
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (result.success && result.data) {
|
|
|
|
|
|
myPhrases.value.unshift(normalizePhrase(result.data, "user"));
|
|
|
|
|
|
uni.showToast({ title: "收藏成功", icon: "success" });
|
|
|
|
|
|
closeCollectPopup();
|
|
|
|
|
|
} else if (result.success) {
|
|
|
|
|
|
await loadMyPhrases();
|
|
|
|
|
|
uni.showToast({ title: "收藏成功", icon: "success" });
|
|
|
|
|
|
closeCollectPopup();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({ title: result.message || "收藏失败", icon: "none" });
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("收藏操作失败:", error);
|
|
|
|
|
|
uni.showToast({ title: "操作失败", icon: "none" });
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-23 15:51:26 +08:00
|
|
|
|
const showAddCategoryDialog = () => {
|
2026-01-26 18:08:01 +08:00
|
|
|
|
editingCategory.value = null;
|
2026-01-23 16:41:39 +08:00
|
|
|
|
categoryForm.value.name = "";
|
2026-01-23 15:51:26 +08:00
|
|
|
|
showCategoryPopup.value = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const editCategory = (category) => {
|
|
|
|
|
|
editingCategory.value = category;
|
|
|
|
|
|
categoryForm.value.name = category.name;
|
|
|
|
|
|
showCategoryPopup.value = true;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-26 18:08:01 +08:00
|
|
|
|
const saveCategory = async () => {
|
2026-01-23 15:51:26 +08:00
|
|
|
|
if (!categoryForm.value.name.trim()) {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: "请输入分类名", icon: "none" });
|
2026-01-23 15:51:26 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
if (categoryForm.value.name.length > 10) {
|
|
|
|
|
|
uni.showToast({ title: "输入内容超过10个字", icon: "none" });
|
2026-01-26 18:08:01 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-01-26 18:08:01 +08:00
|
|
|
|
try {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
const result = await api(editingCategory.value ? "updateUserCommonWordCate" : "addUserCommonWordCate", {
|
|
|
|
|
|
id: editingCategory.value?.id,
|
|
|
|
|
|
label: categoryForm.value.name,
|
2026-01-26 18:08:01 +08:00
|
|
|
|
corpId,
|
|
|
|
|
|
userId,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
if (result.success) {
|
|
|
|
|
|
await loadMyCategories();
|
|
|
|
|
|
uni.showToast({ title: "保存成功", icon: "success" });
|
2026-01-26 18:08:01 +08:00
|
|
|
|
closeCategoryPopup();
|
|
|
|
|
|
} else {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: result.message || "操作失败", icon: "none" });
|
2026-01-26 18:08:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("保存分类失败:", error);
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: "操作失败", icon: "none" });
|
2026-01-26 18:08:01 +08:00
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-23 16:41:39 +08:00
|
|
|
|
const handleCategoryLongPress = (category) => {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
if (activeTab.value !== "mine" || !category.deletable) return;
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: "提示",
|
2026-05-20 16:32:00 +08:00
|
|
|
|
content: `确定删除分类"${category.name}"吗?该分类下的常用语也将被删除。`,
|
2026-01-23 16:41:39 +08:00
|
|
|
|
success: (res) => {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
if (res.confirm) deleteCategory(category);
|
2026-01-23 16:41:39 +08:00
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-26 18:08:01 +08:00
|
|
|
|
const deleteCategory = async (category) => {
|
2026-01-23 16:41:39 +08:00
|
|
|
|
if (!category.deletable) {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: "该分类不可删除", icon: "none" });
|
2026-01-23 16:41:39 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-26 18:08:01 +08:00
|
|
|
|
try {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
const result = await api("deleteUserCommonWordCate", {
|
2026-01-26 18:08:01 +08:00
|
|
|
|
id: category.id,
|
|
|
|
|
|
corpId,
|
|
|
|
|
|
userId,
|
|
|
|
|
|
});
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-01-26 18:08:01 +08:00
|
|
|
|
if (result.success) {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
await loadMyCategories();
|
|
|
|
|
|
await loadMyPhrases();
|
|
|
|
|
|
currentCategory.value = firstMyCategory.value?.id || "";
|
|
|
|
|
|
uni.showToast({ title: "删除成功", icon: "success" });
|
2026-01-26 18:08:01 +08:00
|
|
|
|
} else {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: result.message || "删除失败", icon: "none" });
|
2026-01-26 18:08:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("删除分类失败:", error);
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: "删除失败", icon: "none" });
|
2026-01-26 18:08:01 +08:00
|
|
|
|
}
|
2026-01-23 16:41:39 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-01-23 15:51:26 +08:00
|
|
|
|
const closePopup = () => {
|
|
|
|
|
|
showPhrasePopup.value = false;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
editingPhrase.value = null;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const closeCollectPopup = () => {
|
|
|
|
|
|
showCollectPopup.value = false;
|
|
|
|
|
|
collectingPhrase.value = null;
|
|
|
|
|
|
collectForm.value.cateId = "";
|
2026-01-23 15:51:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const closeCategoryPopup = () => {
|
|
|
|
|
|
showCategoryPopup.value = false;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
editingCategory.value = null;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const loadMyCategories = async () => {
|
|
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
const result = await api("getUserCommonWordCate", { corpId, userId });
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
|
const list = Array.isArray(result.list) ? result.list : [];
|
|
|
|
|
|
myCategories.value = list.map((item) => normalizeCategory(item, "user")).filter((item) => item.id);
|
|
|
|
|
|
if (activeTab.value === "mine") {
|
|
|
|
|
|
currentCategory.value = currentCategory.value || firstMyCategory.value?.id || "";
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({ title: result.message || "加载失败", icon: "none" });
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2026-01-26 18:08:01 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const loadMyPhrases = async () => {
|
|
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
const cateIds = myCategories.value.map((item) => item.id).filter(Boolean);
|
|
|
|
|
|
if (cateIds.length === 0) {
|
|
|
|
|
|
myPhrases.value = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-01-26 18:08:01 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
const result = await api("getCommonWordsList", {
|
|
|
|
|
|
corpId,
|
|
|
|
|
|
userId,
|
|
|
|
|
|
cateIds,
|
|
|
|
|
|
page: 1,
|
|
|
|
|
|
pageSize: 10000,
|
|
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
|
const list = Array.isArray(result.list) ? result.list : [];
|
|
|
|
|
|
myPhrases.value = list.map((item) => normalizePhrase(item, "user")).filter((item) => item.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const loadCorpCategories = async () => {
|
|
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
const result = await api("getCorpCommonWordCate", { corpId, userId }, false);
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
|
const list = Array.isArray(result.list) ? result.list : [];
|
|
|
|
|
|
corpCategories.value = list.map((item) => normalizeCategory(item, "corp")).filter((item) => item.id);
|
|
|
|
|
|
if (activeTab.value === "more" && !currentCategory.value) {
|
|
|
|
|
|
currentCategory.value = corpCategories.value[0]?.id || "";
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const loadCorpPhrases = async () => {
|
|
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
const cateIds = corpCategories.value.map((item) => item.id).filter(Boolean);
|
|
|
|
|
|
if (cateIds.length === 0) {
|
|
|
|
|
|
corpPhrases.value = [];
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const result = await api("getCommonWordsList", {
|
|
|
|
|
|
corpId,
|
|
|
|
|
|
userId,
|
|
|
|
|
|
cateIds,
|
|
|
|
|
|
page: 1,
|
|
|
|
|
|
pageSize: 10000,
|
|
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
|
|
|
|
if (result.success) {
|
|
|
|
|
|
const list = Array.isArray(result.list) ? result.list : [];
|
|
|
|
|
|
corpPhrases.value = list.map((item) => normalizePhrase(item, "corp")).filter((item) => item.id);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const loadAll = async () => {
|
|
|
|
|
|
const { corpId, userId } = getAccountParams();
|
|
|
|
|
|
if (!corpId || !userId) {
|
|
|
|
|
|
uni.showToast({ title: "请先登录", icon: "none" });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
await loadMyCategories();
|
|
|
|
|
|
await loadMyPhrases();
|
|
|
|
|
|
await loadCorpCategories();
|
|
|
|
|
|
await loadCorpPhrases();
|
2026-01-23 15:51:26 +08:00
|
|
|
|
} catch (error) {
|
2026-01-26 18:08:01 +08:00
|
|
|
|
console.error("加载常用语失败:", error);
|
2026-05-20 16:32:00 +08:00
|
|
|
|
uni.showToast({ title: "加载失败", icon: "none" });
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
loadAll();
|
2026-01-23 15:51:26 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2026-05-20 16:32:00 +08:00
|
|
|
|
$primary-color: #1f5cff;
|
|
|
|
|
|
$primary-light: #eef4ff;
|
|
|
|
|
|
$text-main: #222;
|
|
|
|
|
|
$border-color: #edf0f5;
|
2026-01-23 16:09:34 +08:00
|
|
|
|
|
2026-01-23 15:51:26 +08:00
|
|
|
|
.common-phrases-page {
|
2026-02-04 18:50:20 +08:00
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
bottom: 20rpx;
|
2026-01-23 16:41:39 +08:00
|
|
|
|
display: flex;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
background: #f7f8fb;
|
2026-01-23 16:41:39 +08:00
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.tabs-bar {
|
2026-01-23 16:41:39 +08:00
|
|
|
|
display: flex;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
height: 96rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-bottom: 1px solid $border-color;
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.tab-item {
|
2026-01-23 16:41:39 +08:00
|
|
|
|
flex: 1;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
position: relative;
|
2026-01-23 16:41:39 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
color: #4b5565;
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 500;
|
2026-01-26 18:08:01 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
&.active {
|
2026-01-26 18:08:01 +08:00
|
|
|
|
color: $primary-color;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
|
|
|
|
|
|
&::after {
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
bottom: 14rpx;
|
|
|
|
|
|
width: 70rpx;
|
|
|
|
|
|
height: 6rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
background: $primary-color;
|
|
|
|
|
|
transform: translateX(-50%);
|
|
|
|
|
|
}
|
2026-01-26 18:08:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-23 16:09:34 +08:00
|
|
|
|
.content-wrapper {
|
|
|
|
|
|
flex: 1;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
min-height: 0;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
display: flex;
|
2026-01-23 16:09:34 +08:00
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-01-23 16:09:34 +08:00
|
|
|
|
.category-sidebar {
|
2026-01-26 18:08:01 +08:00
|
|
|
|
width: 210rpx;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
flex-shrink: 0;
|
2026-01-26 18:08:01 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-right: 1px solid $border-color;
|
2026-01-23 16:09:34 +08:00
|
|
|
|
|
|
|
|
|
|
.category-list {
|
2026-01-26 18:08:01 +08:00
|
|
|
|
flex: 1;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
min-height: 0;
|
2026-01-23 16:09:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.category-item {
|
|
|
|
|
|
position: relative;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
min-height: 88rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 12rpx 16rpx;
|
|
|
|
|
|
color: #344054;
|
|
|
|
|
|
background: #fff;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
|
|
|
|
|
&.active {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
color: $primary-color;
|
|
|
|
|
|
background: $primary-light;
|
|
|
|
|
|
|
|
|
|
|
|
&::before {
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
top: 20rpx;
|
|
|
|
|
|
bottom: 20rpx;
|
|
|
|
|
|
width: 4rpx;
|
|
|
|
|
|
border-radius: 999rpx;
|
|
|
|
|
|
background: $primary-color;
|
|
|
|
|
|
}
|
2026-01-23 16:09:34 +08:00
|
|
|
|
|
|
|
|
|
|
.category-name {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
font-weight: 700;
|
2026-01-23 16:09:34 +08:00
|
|
|
|
}
|
2026-01-23 16:41:39 +08:00
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
}
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.category-content {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.category-name {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
line-height: 40rpx;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.delete-badge {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: -22rpx;
|
|
|
|
|
|
right: -8rpx;
|
|
|
|
|
|
width: 30rpx;
|
|
|
|
|
|
height: 30rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
background: #ff3b30;
|
|
|
|
|
|
|
|
|
|
|
|
.delete-icon {
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
line-height: 1;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-26 18:08:01 +08:00
|
|
|
|
.add-category-footer {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
min-height: 104rpx;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-01-23 16:09:34 +08:00
|
|
|
|
justify-content: center;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
border-top: 1px solid $border-color;
|
|
|
|
|
|
background: #fff;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-01-26 18:08:01 +08:00
|
|
|
|
.add-category-text {
|
2026-01-23 16:41:39 +08:00
|
|
|
|
color: $primary-color;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: 600;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-23 16:09:34 +08:00
|
|
|
|
.phrases-container {
|
|
|
|
|
|
flex: 1;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
min-width: 0;
|
2026-01-23 16:09:34 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
background: #f7f8fb;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.list-header {
|
|
|
|
|
|
padding: 22rpx 24rpx 14rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.current-title {
|
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.search-box {
|
|
|
|
|
|
height: 64rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 0 20rpx;
|
|
|
|
|
|
border-radius: 32rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid $border-color;
|
|
|
|
|
|
|
|
|
|
|
|
.search-icon {
|
|
|
|
|
|
margin-right: 10rpx;
|
|
|
|
|
|
color: #98a2b3;
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.search-input {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
height: 64rpx;
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.clear-search {
|
|
|
|
|
|
width: 36rpx;
|
|
|
|
|
|
height: 36rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
color: #98a2b3;
|
|
|
|
|
|
font-size: 34rpx;
|
|
|
|
|
|
}
|
2026-01-23 16:09:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-23 15:51:26 +08:00
|
|
|
|
.phrases-list {
|
|
|
|
|
|
flex: 1;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
min-height: 0;
|
|
|
|
|
|
padding: 0 24rpx 24rpx;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.phrase-item {
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
padding: 24rpx 24rpx 18rpx;
|
|
|
|
|
|
border-radius: 14rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid $border-color;
|
|
|
|
|
|
box-shadow: 0 8rpx 24rpx rgba(16, 24, 40, 0.04);
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.phrase-top {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.phrase-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
min-width: 0;
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
line-height: 44rpx;
|
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.collected-badge {
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
padding: 4rpx 10rpx;
|
|
|
|
|
|
color: $primary-color;
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
border-radius: 6rpx;
|
|
|
|
|
|
background: $primary-light;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.phrase-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 28rpx;
|
|
|
|
|
|
margin-top: 20rpx;
|
|
|
|
|
|
padding-top: 16rpx;
|
|
|
|
|
|
border-top: 1px solid $border-color;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.action-btn {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 6rpx;
|
|
|
|
|
|
color: #475467;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.action-icon {
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
line-height: 1;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
&.send,
|
|
|
|
|
|
&.collect.collected {
|
|
|
|
|
|
color: $primary-color;
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
&.delete {
|
|
|
|
|
|
color: #ff3b30;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.collect-tip {
|
|
|
|
|
|
padding: 8rpx 0 28rpx;
|
|
|
|
|
|
color: #98a2b3;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.empty-state {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 180rpx 24rpx;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
|
|
|
|
.empty-text {
|
|
|
|
|
|
color: #667085;
|
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.empty-hint {
|
|
|
|
|
|
margin-top: 14rpx;
|
|
|
|
|
|
color: #98a2b3;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.footer-action-bar {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 18rpx;
|
|
|
|
|
|
padding: 22rpx 24rpx 28rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-top: 1px solid $border-color;
|
|
|
|
|
|
|
|
|
|
|
|
.add-phrase-btn {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
height: 76rpx;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
gap: 10rpx;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
background: $primary-color;
|
|
|
|
|
|
border-radius: 18rpx;
|
|
|
|
|
|
box-shadow: 0 8rpx 20rpx rgba(31, 92, 255, 0.22);
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.add-icon,
|
|
|
|
|
|
.add-text,
|
|
|
|
|
|
.edit-text {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.edit-btn {
|
|
|
|
|
|
width: 112rpx;
|
|
|
|
|
|
height: 76rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
color: $primary-color;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.popup-mask {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
top: 0;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
bottom: 0;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
z-index: 9999;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
display: flex;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
align-items: flex-end;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
justify-content: center;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
background: rgba(0, 0, 0, 0.45);
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.popup-content {
|
2026-05-20 16:32:00 +08:00
|
|
|
|
width: 100%;
|
|
|
|
|
|
padding: 34rpx 32rpx 40rpx;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 28rpx 28rpx 0 0;
|
|
|
|
|
|
box-shadow: 0 -10rpx 30rpx rgba(16, 24, 40, 0.12);
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-01-23 16:41:39 +08:00
|
|
|
|
.popup-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
2026-05-20 16:32:00 +08:00
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
|
|
}
|
2026-01-23 16:41:39 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.popup-title {
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
font-size: 34rpx;
|
|
|
|
|
|
font-weight: 700;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.popup-close {
|
|
|
|
|
|
width: 48rpx;
|
|
|
|
|
|
height: 48rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-01-23 16:41:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.close-icon {
|
|
|
|
|
|
color: #98a2b3;
|
|
|
|
|
|
font-size: 46rpx;
|
|
|
|
|
|
line-height: 1;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-label {
|
|
|
|
|
|
margin-bottom: 14rpx;
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-label {
|
|
|
|
|
|
margin-top: 30rpx;
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.category-picker,
|
|
|
|
|
|
.category-input {
|
|
|
|
|
|
height: 84rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
padding: 0 22rpx;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
border: 1px solid #d9e0ea;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.picker-arrow {
|
|
|
|
|
|
color: #667085;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-hint {
|
|
|
|
|
|
margin-top: 12rpx;
|
|
|
|
|
|
color: #98a2b3;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.collect-preview {
|
|
|
|
|
|
margin: 28rpx 0 32rpx;
|
|
|
|
|
|
padding: 22rpx;
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
line-height: 42rpx;
|
|
|
|
|
|
word-break: break-word;
|
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
background: #f7f8fb;
|
|
|
|
|
|
border: 1px solid $border-color;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.phrase-textarea {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 220rpx;
|
|
|
|
|
|
padding: 22rpx;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
line-height: 42rpx;
|
|
|
|
|
|
border: 1px solid #d9e0ea;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.char-count {
|
|
|
|
|
|
margin-top: 12rpx;
|
|
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
|
|
color: #98a2b3;
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.category-popup {
|
2026-01-23 15:51:26 +08:00
|
|
|
|
.category-input {
|
|
|
|
|
|
width: 100%;
|
2026-01-23 16:41:39 +08:00
|
|
|
|
margin-bottom: 32rpx;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
.popup-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 24rpx;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
button {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
height: 78rpx;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
border-radius: 14rpx;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
|
2026-05-20 16:32:00 +08:00
|
|
|
|
&::after {
|
|
|
|
|
|
border: 0;
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-05-20 16:32:00 +08:00
|
|
|
|
|
|
|
|
|
|
.cancel-btn {
|
|
|
|
|
|
color: $text-main;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid #d9e0ea;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.confirm-btn {
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
background: $primary-color;
|
|
|
|
|
|
}
|
2026-01-23 15:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|