完善页面5

This commit is contained in:
2026-02-26 09:17:30 +08:00
parent 455e4536d4
commit ff10f495ad
3 changed files with 792 additions and 45 deletions

View File

@@ -32,6 +32,7 @@
<view class="th col-id"><text class="th-txt">ID</text></view>
<view class="th col-img"><text class="th-txt">文章图片</text></view>
<view class="th col-name"><text class="th-txt">文章名称</text></view>
<view class="th col-cat"><text class="th-txt">文章分类</text></view>
<view class="th col-link"><text class="th-txt">关联商品</text></view>
<view class="th col-v"><text class="th-txt">浏览量</text></view>
<view class="th col-time"><text class="th-txt">时间</text></view>
@@ -45,6 +46,7 @@
<view class="img-box"><text class="img-placeholder">🖼️</text></view>
</view>
<view class="td col-name"><text class="td-txt">{{ item.name }}</text></view>
<view class="td col-cat"><text class="td-txt">{{ item.categoryName }}</text></view>
<view class="td col-link"><text class="td-txt">{{ item.linkedProduct }}</text></view>
<view class="td col-v"><text class="td-txt">{{ item.views }}</text></view>
<view class="td col-time"><text class="td-txt">{{ item.time }}</text></view>
@@ -112,11 +114,20 @@
<view class="form-row mt-20">
<view class="form-col">
<view class="label-box"><text class="required">*</text><text class="label-txt">文章分类:</text></view>
<view class="input-box">
<view class="select-mock">
<view class="input-box z-20" style="position: relative;">
<view class="select-mock" @click.stop="toggleDropdown">
<text class="select-val">{{ formCategory || '请选择' }}</text>
<text class="arrow-down">▼</text>
</view>
<view v-if="dropdownVisible" class="dropdown-list" @click.stop="">
<view
v-for="(cat, index) in categoryList"
:key="index"
class="dropdown-item"
@click="selectCategory(cat)">
<text class="dropdown-txt">{{ cat }}</text>
</view>
</view>
</view>
</view>
<view class="form-col">
@@ -131,7 +142,7 @@
<view class="form-row mt-20">
<view class="form-col full">
<view class="label-box"><text class="required">*</text><text class="label-txt">图文封面:</text></view>
<view class="upload-container">
<view class="upload-container" @click="handleUploadCover">
<view class="upload-btn">
<text class="plus-icon">+</text>
</view>
@@ -153,18 +164,14 @@
<view class="label-box mb-10"><text class="required">*</text><text class="label-txt">文章内容:</text></view>
<view class="rich-editor-mock">
<view class="editor-toolbar">
<text class="tool-ic">HTML</text>
<text class="tool-ic">H</text>
<text class="tool-ic">B</text>
<text class="tool-ic">T↕</text>
<text class="tool-ic">F</text>
<text class="tool-ic">I</text>
<text class="tool-ic">U</text>
<text class="tool-ic">S</text>
<text class="tool-ic-img">🖼️</text>
<text class="tool-ic-img">🎬</text>
<text class="tool-ic" @click="formatText('bold')">B</text>
<text class="tool-ic" @click="formatText('italic')">I</text>
<text class="tool-ic" @click="formatText('underline')">U</text>
<text class="tool-ic" @click="insertImage">🖼️</text>
</view>
<view class="editor-content-container">
<editor id="editor" class="editor-instance" placeholder="在此输入文章内容..." @ready="onEditorReady"></editor>
</view>
<view class="editor-content"></view>
</view>
</view>
@@ -223,38 +230,83 @@ import { ref } from 'vue'
const filterCategory = ref('全部')
const filterKeyword = ref('')
const articleList = ref([
{ id: '240', name: '赋能消费 | 卷狗优选迈向文化消费新时代', linkedProduct: '', views: '3349', time: '2025-04-01 16:34' },
{ id: '237', name: '把重要的日子放在桌面', linkedProduct: '2024新款吹风机...', views: '260', time: '2025-04-01 16:32' }
{ id: '240', name: '赋能消费 | 卷狗优选迈向文化消费新时代', categoryName:'消费文化', linkedProduct: '', views: '3349', time: '2025-04-01 16:34' },
{ id: '237', name: '把重要的日子放在桌面', categoryName:'品牌资讯', linkedProduct: '2024新款吹风机...', views: '260', time: '2025-04-01 16:32' }
])
const categoryList = ref(['购物心得', '消费文化', '品牌资讯', '全部']) // Mock data mirroring categories
const dropdownVisible = ref(false)
const showDrawer = ref(false)
const isClosing = ref(false)
const formTitle = ref('')
const formAuthor = ref('')
const formCategory = ref('')
const formIntro = ref('')
const formContent = ref('')
const formBanner = ref(false)
const formHot = ref(false)
const toggleDropdown = () => {
dropdownVisible.value = !dropdownVisible.value
}
const selectCategory = (cat: string) => {
formCategory.value = cat
dropdownVisible.value = false
}
const handleAdd = () => {
let editorCtx: any = null
const onEditorReady = () => {
// @ts-ignore
uni.createSelectorQuery().select('#editor').context((res) => {
editorCtx = res.context
}).exec()
}
const formatText = (name: string) => {
if (editorCtx) {
editorCtx.format(name)
}
}
const insertImage = () => {
uni.chooseImage({
count: 1,
success: (res) => {
if (editorCtx) {
editorCtx.insertImage({
src: res.tempFilePaths[0],
alt: '图像'
})
}
}
})
}
formTitle.value = ''
formAuthor.value = ''
formCategory.value = ''
formIntro.value = ''
formContent.value = ''
formBanner.value = false
formHot.value = false
isClosing.value = false
dropdownVisible.value = false
showDrawer.value = true
}
const handleEdit = (item: any) => {
formTitle.value = item.name
formAuthor.value = '管理员'
formCategory.value = '全部'
formCategory.value = item.categoryName
formIntro.value = '这是一段文章简介...'
formContent.value = '<p>这是一段富文本内容...</p>'
formBanner.value = false
formHot.value = true
isClosing.value = false
dropdownVisible.value = false
showDrawer.value = true
}
@@ -265,7 +317,38 @@ const closeDrawer = () => {
isClosing.value = false
}, 300)
}
const handleConfirm = () => { closeDrawer() }
const handleUploadCover = () => {
uni.chooseImage({
count: 1,
success: (res) => {
// 在实际应用中这里应该上传到服务器
// 这里简单模拟展示
uni.showToast({ title: '上传成功', icon: 'success' })
// formCover.value = res.tempFilePaths[0]
}
})
}
const handleConfirm = () => {
if (formTitle.value.trim() == '') {
uni.showToast({ title: '请输入标题', icon: 'none' })
return
}
// 模拟保存逻辑
const newId = String(241 + articleList.value.length)
articleList.value.unshift({
id: newId,
name: formTitle.value,
categoryName: formCategory.value || '未分类',
linkedProduct: '',
views: '0',
time: '2026-02-26 12:00'
})
uni.showToast({ title: '发布成功', icon: 'success' })
closeDrawer()
}
const handleQuery = () => { console.log('Querying...') }
</script>
@@ -296,6 +379,7 @@ const handleQuery = () => { console.log('Querying...') }
.col-id { width: 80px; justify-content: center; }
.col-img { width: 100px; }
.col-name { flex: 2; }
.col-cat { width: 120px; }
.col-link { flex: 2; }
.col-v { width: 100px; justify-content: center; }
.col-time { width: 180px; justify-content: center; }
@@ -339,6 +423,7 @@ const handleQuery = () => { console.log('Querying...') }
.label-txt { font-size: 14px; color: #606266; }
.input-box { flex: 1; position: relative; }
.z-20 { z-index: 20; }
.input-base { width: 100%; height: 38px; border: 1px solid #dcdee2; border-radius: 4px; padding: 0 45px 0 12px; font-size: 14px; }
.textarea-base { width: 100%; height: 100px; border: 1px solid #dcdee2; border-radius: 4px; padding: 10px 12px; font-size: 14px; }
.input-count { position: absolute; bottom: 8px; right: 12px; font-size: 12px; color: #999; }
@@ -351,9 +436,10 @@ const handleQuery = () => { console.log('Querying...') }
.editor-section { display: flex; flex-direction: column; }
.rich-editor-mock { border: 1px solid #dcdee2; border-radius: 4px; min-height: 400px; display: flex; flex-direction: column; }
.editor-toolbar { height: 44px; background-color: #fafafa; border-bottom: 1px solid #dcdee2; display: flex; flex-direction: row; align-items: center; padding: 0 15px; gap: 20px; flex-wrap: wrap; }
.tool-ic { font-size: 14px; color: #515a6e; cursor: pointer; }
.tool-ic-img { font-size: 18px; cursor: pointer; }
.editor-content { flex: 1; background-color: #fff; }
.tool-ic { font-size: 16px; color: #515a6e; cursor: pointer; padding: 5px 10px; border: 1px solid #eee; border-radius: 4px; }
.tool-ic:active { background-color: #f0f0f0; }
.editor-content-container { flex: 1; background-color: #fff; padding: 15px; }
.editor-instance { width: 100%; height: 350px; font-size: 14px; }
.settings-section { display: flex; flex-direction: column; }
.form-item { display: flex; flex-direction: row; align-items: center; }
@@ -365,6 +451,35 @@ const handleQuery = () => { console.log('Querying...') }
.radio-in { width: 8px; height: 8px; background-color: #2d8cf0; border-radius: 50%; }
.radio-la { font-size: 14px; color: #606266; }
.dropdown-list {
position: absolute;
top: 40px;
left: 0;
width: 100%;
background-color: #fff;
border: 1px solid #dcdee2;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
z-index: 100;
max-height: 200px;
overflow-y: auto;
}
.dropdown-item {
padding: 10px 15px;
cursor: pointer;
border-bottom: 1px solid #f0f0f0;
}
.dropdown-item:last-child {
border-bottom: none;
}
.dropdown-item:hover {
background-color: #f5f7fa;
}
.dropdown-txt {
font-size: 14px;
color: #606266;
}
.submit-container { display: flex; justify-content: flex-start; padding-left: 135px; padding-bottom: 50px; }
.btn-submit { width: 120px; height: 40px; background-color: #2d8cf0; border-radius: 4px; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.submit-txt { color: #fff; font-size: 14px; }

View File

@@ -73,11 +73,20 @@
<scroll-view class="drawer-body" :scroll-y="true">
<view class="form-item row">
<view class="label-box"><text class="label-txt">上级分类:</text></view>
<view class="input-box">
<view class="select-mock">
<text class="select-val">顶级分类</text>
<text class="arrow-down">▼</text>
</view>
<view class="input-box z-10" style="position: relative;">
<view class="select-mock" @click="toggleParentDropdown">
<text class="select-val">{{ formParentCategory }}</text>
<text class="arrow-down">▼</text>
</view>
<view v-if="parentDropdownVisible" class="dropdown-list">
<view
v-for="(cat, index) in parentCategoryList"
:key="index"
class="dropdown-item"
@click="selectParentCategory(cat)">
<text class="dropdown-txt">{{ cat }}</text>
</view>
</view>
</view>
</view>
@@ -98,8 +107,9 @@
<view class="form-item row">
<view class="label-box"><text class="label-txt">分类图片:</text></view>
<view class="input-box">
<view class="upload-btn">
<view class="img-icon">🖼️</view>
<view class="upload-btn" @click="handleUpload">
<view v-if="!formImage" class="img-icon">🖼️</view>
<text v-else style="font-size:12px;">已上传</text>
</view>
</view>
</view>
@@ -151,23 +161,48 @@ const formName = ref('')
const formDesc = ref('')
const formSort = ref(0)
const formStatus = ref(true)
const formParentCategory = ref('顶级分类')
const formImage = ref('')
const parentCategoryList = ref(['顶级分类', '购物心得', '消费文化', '品牌资讯'])
const parentDropdownVisible = ref(false)
const toggleParentDropdown = () => {
parentDropdownVisible.value = !parentDropdownVisible.value
}
const selectParentCategory = (val: string) => {
formParentCategory.value = val
parentDropdownVisible.value = false
}
const handleUpload = () => {
formImage.value = 'uploaded'
uni.showToast({ title: '模拟上传图片', icon: 'none' })
}
const handleAdd = () => {
formName.value = ''
formDesc.value = ''
formSort.value = 0
formStatus.value = true
formParentCategory.value = '顶级分类'
formImage.value = ''
isClosing.value = false
parentDropdownVisible.value = false
showDrawer.value = true
}
const handleEdit = (item: any) => {
formName.value = item.name
// 模拟填充其他字段
formDesc.value = ''
formDesc.value = '分类简介...'
formSort.value = 0
formStatus.value = item.status
formParentCategory.value = '顶级分类'
formImage.value = 'exists'
isClosing.value = false
parentDropdownVisible.value = false
showDrawer.value = true
}
@@ -182,7 +217,23 @@ const closeDrawer = () => {
isClosing.value = false
}, 300)
}
const handleConfirm = () => { closeDrawer() }
const handleConfirm = () => {
if (formName.value.trim() == '') {
uni.showToast({ title: '请输入分类名称', icon: 'none' })
return
}
// 模拟保存逻辑
const newId = String(182 + categoryList.value.length)
categoryList.value.unshift({
id: newId,
name: formName.value,
status: formStatus.value
})
uni.showToast({ title: '添加成功', icon: 'success' })
closeDrawer()
}
const handleQuery = () => { console.log('Querying...') }
</script>
@@ -238,6 +289,35 @@ const handleQuery = () => { console.log('Querying...') }
.label-txt { font-size: 14px; color: #606266; text-align: right; }
.input-box { flex: 1; }
.input-base { width: 100%; height: 38px; border: 1px solid #dcdee2; border-radius: 4px; padding: 0 12px; font-size: 14px; }
.dropdown-list {
position: absolute;
top: 40px;
left: 0;
width: 100%;
background-color: #fff;
border: 1px solid #dcdee2;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
z-index: 100;
max-height: 200px;
overflow-y: auto;
}
.dropdown-item {
padding: 10px 15px;
cursor: pointer;
border-bottom: 1px solid #f0f0f0;
}
.dropdown-item:last-child {
border-bottom: none;
}
.dropdown-item:hover {
background-color: #f5f7fa;
}
.dropdown-txt {
font-size: 14px;
color: #606266;
}
.textarea-mini { width: 100%; height: 80px; border: 1px solid #dcdee2; border-radius: 4px; padding: 10px 12px; font-size: 14px; }
.upload-btn {