refactor(component): 重构组件模板与样式结构

将公共样式提取至public.css,优化组件模板结构
添加图片资源与组件模板同步脚本
调整组件样式与布局,统一风格
This commit is contained in:
DESKTOP-RQ919RC\Pc
2025-10-22 18:31:16 +08:00
parent 5b4040ec05
commit 6bb48ff86d
31 changed files with 3067 additions and 613 deletions

View File

@@ -0,0 +1,24 @@
// my-component.js
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入Vue 已挂载到 window
const { defineComponent, ref } = Vue;
// 定义组件(直接使用模板)
export const itemBottom = defineComponent({
name: "item-bottom",
props: {
title: {
type: String,
default: "默认标题",
},
itemdata: {
type: Object,
default: () => {},
},
},
setup(props) {
let item = ref({ ...props.itemdata });
return { item };
},
template: `<div class="comment flexacenter" v-if="!Array.isArray(item?.commentreviews)"> <img class="icon" :src="item?.commentreviews?.avatar" /> <div class="text one-line-display">{{ item?.commentreviews?.content }}</div></div><div class="bottom flexacenter"> <div class="bottom-item like flexacenter"> <img class="icon" src="./img/like-icon.png" /> <div class="text">{{ item.likes || "赞" }}</div> </div> <div class="bottom-item like flexacenter"> <img class="icon" src="./img/collect-golden.svg" /> <div class="text">{{ item.collections || "收藏" }}</div> </div> <div class="bottom-item like flexacenter"> <img class="icon" src="./img/discuss-icon.png" /> <div class="text">{{ item.comments || "讨论" }}</div> </div> <div class="bottom-item like flexacenter"> <img class="icon" src="./img/bi-copper-icon.png" /> <div class="text">{{ item.coins || "投币" }}</div> </div> <div class="bottom-item like flexacenter"> <img class="icon" src="./img/share-gray.png" /> <div class="text">转发</div> </div></div>`,
});

View File

@@ -0,0 +1,28 @@
<div class="comment flexacenter" v-if="!Array.isArray(item?.commentreviews)">
<img class="icon" :src="item?.commentreviews?.avatar" />
<div class="text one-line-display">{{ item?.commentreviews?.content }}</div>
</div>
<div class="bottom flexacenter">
<div class="bottom-item like flexacenter">
<img class="icon" src="./img/like-icon.png" />
<div class="text">{{ item.likes || "赞" }}</div>
</div>
<div class="bottom-item like flexacenter">
<img class="icon" src="./img/collect-golden.svg" />
<div class="text">{{ item.collections || "收藏" }}</div>
</div>
<div class="bottom-item like flexacenter">
<img class="icon" src="./img/discuss-icon.png" />
<div class="text">{{ item.comments || "讨论" }}</div>
</div>
<div class="bottom-item like flexacenter">
<img class="icon" src="./img/bi-copper-icon.png" />
<div class="text">{{ item.coins || "投币" }}</div>
</div>
<div class="bottom-item like flexacenter">
<img class="icon" src="./img/share-gray.png" />
<div class="text">转发</div>
</div>
</div>

View File

@@ -1,11 +1,12 @@
// my-component.js
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入Vue 已挂载到 window
const { defineComponent } = Vue;
console.log("11223131321321");
import { itemBottom } from "../item-bottom/item-bottom.js";
import { itemHead } from "../item-head/item-head.js";
// 定义组件(直接使用模板)
export const MyComponent = defineComponent({
name: "MyComponent",
export const itemForum = defineComponent({
name: "item-forum",
props: {
title: {
type: String,
@@ -18,10 +19,11 @@ export const MyComponent = defineComponent({
alert("组件按钮被点击");
},
},
// 直接使用template选项包含标题、文本内容和按钮
template: `<div style="padding: 10px; border: 1px solid #ccc;">
<h3>{{ title }}</h3>
<p>这是从text文件加载的模板内容</p>
<button @click="handleClick">点击我</button>
</div>`,
components: {
itemBottom,
itemHead,
},
template: `<div class="item-box item-forum"> <item-head></item-head> <div class="label flexflex"> <img class="item icon" src="./img/recommend-icon.png" /> <img class="item icon" src="./img/essence-icon.png" /> <div class="item blue">香港</div> <div class="item">香港</div> </div> <div class="title">【干货】香港留学费用准备</div> <div class="message">在即将赴港的时候很多同学好奇香港一年制硕士下来的整体费用大概是多少其实主要包括学费租房费和生活费三部分。学费的话根据不同香港来定大概在10-30万港币之间比较固定…</div> <item-bottom></item-bottom></div>`,
});

View File

@@ -1,5 +0,0 @@
<div style="padding: 10px; border: 1px solid #ccc;">
<h3>{{ title }}</h3>
<p>这是从text文件加载的模板内容</p>
<button @click="handleClick">点击我</button>
</div>

View File

@@ -0,0 +1,15 @@
<div class="item-box item-forum">
<item-head></item-head>
<div class="label flexflex">
<img class="item icon" src="./img/recommend-icon.png" />
<img class="item icon" src="./img/essence-icon.png" />
<div class="item blue">香港</div>
<div class="item">香港</div>
</div>
<div class="title">【干货】香港留学费用准备</div>
<div class="message">在即将赴港的时候很多同学好奇香港一年制硕士下来的整体费用大概是多少其实主要包括学费租房费和生活费三部分。学费的话根据不同香港来定大概在10-30万港币之间比较固定…</div>
<item-bottom></item-bottom>
</div>

View File

@@ -0,0 +1,22 @@
// my-component.js
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入Vue 已挂载到 window
const { defineComponent } = Vue;
// 定义组件(直接使用模板)
export const itemHead = defineComponent({
name: "item-head",
props: {
title: {
type: String,
default: "默认标题",
},
},
// 方法
methods: {
handleClick() {
alert("组件按钮被点击");
},
},
template: `<div class="item-head flexacenter"> <img class="avatar" src="https://nas.gter.net:9008/avatar/97K4EWIMLrsbGTWXslC1UltTF6WOikN42jDKLNjtax7Hc44zLpaKSdU9oWFhY2E~/small" /> <div class="name">小P学姐</div> <img class="group" src="https://o.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-c_ZMtdXfqqsgFptxhcq_cQnrlcPJ0DVESBq_D-81qNDQyOQ~~" /> <div class="time">2025-8-11 01:30</div> <div class="flex1"></div> <div class="view flexacenter"> <img class="icon" src="https://app.gter.net/image/miniApp/offer/eye-icon.svg" /> <div class="text">3016</div> </div> <div class="btn flexcenter" @click="cutShow"> <img class="icon" src="https://app.gter.net/image/miniApp/offer/dot-dot-dot-gray.png" /> </div> <!-- <template v-if="show"> <div class="mask" catch:tap="cutShow" catch:touchmove="touchmove"></div> <div class="operate" catch:tap="true"> <div class="item" bind:tap="report">举报</div> <template v-if="ismanager"> <div class="item" bind:tap="hide">{{ item.hidden == 0 ? '隐藏' : '显示' }}</div> <div class="item" bind:tap="recommend">{{ item.recommend == 1 ? '取消' : '' }}推荐</div> <div class="item" bind:tap="essence">{{ item.best == 1 ? '取消' : '' }}精华</div> </template> </div> </template> --></div> `,
});

View File

@@ -0,0 +1,28 @@
<div class="item-head flexacenter">
<img class="avatar" src="https://nas.gter.net:9008/avatar/97K4EWIMLrsbGTWXslC1UltTF6WOikN42jDKLNjtax7Hc44zLpaKSdU9oWFhY2E~/small" />
<div class="name">小P学姐</div>
<img class="group" src="https://o.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-c_ZMtdXfqqsgFptxhcq_cQnrlcPJ0DVESBq_D-81qNDQyOQ~~" />
<div class="time">2025-8-11 01:30</div>
<div class="flex1"></div>
<div class="view flexacenter">
<img class="icon" src="https://app.gter.net/image/miniApp/offer/eye-icon.svg" />
<div class="text">3016</div>
</div>
<div class="btn flexcenter" @click="cutShow">
<img class="icon" src="https://app.gter.net/image/miniApp/offer/dot-dot-dot-gray.png" />
</div>
<!-- <template v-if="show">
<div class="mask" catch:tap="cutShow" catch:touchmove="touchmove"></div>
<div class="operate" catch:tap="true">
<div class="item" bind:tap="report">举报</div>
<template v-if="ismanager">
<div class="item" bind:tap="hide">{{ item.hidden == 0 ? '隐藏' : '显示' }}</div>
<div class="item" bind:tap="recommend">{{ item.recommend == 1 ? '取消' : '' }}推荐</div>
<div class="item" bind:tap="essence">{{ item.best == 1 ? '取消' : '' }}精华</div>
</template>
</div>
</template> -->
</div>

View File

@@ -0,0 +1,33 @@
// my-component.js
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入Vue 已挂载到 window
const { defineComponent } = Vue;
import { itemBottom } from "../item-bottom/item-bottom.js";
import { itemHead } from "../item-head/item-head.js";
// 定义组件(直接使用模板)
export const itemOffer = defineComponent({
name: "item-offer",
props: {
title: {
type: String,
default: "默认标题",
},
item: {
type: Object,
default: () => {},
},
},
// 方法
methods: {
handleClick() {
alert("组件按钮被点击");
},
},
components: {
itemBottom,
itemHead,
},
template: `<div class="item-box item-offer"> <item-head></item-head> <div class="school flexacenter"> <img class="icon" :src="item.data.schoollogo" mode="heightFix"></image> <div class="text flex1 one-line-display">{{ item.data.schoolname }}</div> </div> <div class="major flexacenter" v-if="item.data.professional"> <div class="key">{{ item.data.project ? '专业' : '项目/专业' }}</div> <div class="value flex1 one-line-display">{{ item.data.professional }}</div> </div> <div class="major flexacenter" v-if="item.data.project"> <div class="key">项目</div> <div class="value flex1 one-line-display">{{ item.data.project }}</div> </div> <div class="info flexacenter"> {{ item.data.semester }} <div class="line"></div> {{ item.data.degree }} <div class="line"></div> <div class="results" :class="['r' + item.data.apply_results]">{{ item.data.apply_results_text }}</div> </div> <div class="message" v-if="item.content">{{ item.content }}</div> <item-bottom></item-bottom></div>`,
});

View File

@@ -0,0 +1,28 @@
<div class="item-box item-offer">
<item-head></item-head>
<div class="school flexacenter">
<img class="icon" :src="item.data.schoollogo" mode="heightFix"></image>
<div class="text flex1 one-line-display">{{ item.data.schoolname }}</div>
</div>
<div class="major flexacenter" v-if="item.data.professional">
<div class="key">{{ item.data.project ? '专业' : '项目/专业' }}</div>
<div class="value flex1 one-line-display">{{ item.data.professional }}</div>
</div>
<div class="major flexacenter" v-if="item.data.project">
<div class="key">项目</div>
<div class="value flex1 one-line-display">{{ item.data.project }}</div>
</div>
<div class="info flexacenter">
{{ item.data.semester }}
<div class="line"></div>
{{ item.data.degree }}
<div class="line"></div>
<div class="results" :class="['r' + item.data.apply_results]">{{ item.data.apply_results_text }}</div>
</div>
<div class="message" v-if="item.content">{{ item.content }}</div>
<item-bottom></item-bottom>
</div>

View File

@@ -0,0 +1,33 @@
// my-component.js
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入Vue 已挂载到 window
const { defineComponent } = Vue;
import { itemBottom } from "../item-bottom/item-bottom.js";
import { itemHead } from "../item-head/item-head.js";
// 定义组件(直接使用模板)
export const itemSummary = defineComponent({
name: "item-summary",
props: {
title: {
type: String,
default: "默认标题",
},
item: {
type: Object,
default: () => {},
},
},
// 方法
methods: {
handleClick() {
alert("组件按钮被点击");
},
},
components: {
itemBottom,
itemHead,
},
template: `<div class="item-box item-summary"> <item-head></item-head> <div class="title" v-if="item.title">{{ item.title }}</div> <div class="message one-line-display" v-if="item.content">{{ item.content }}</div> <div class="total flexacenter"> <div>共</div> <div class="num">{{ item.data.offercount }}</div> <div>个Offer</div> </div> <div class="list flexacenter" scroll-x> <div class="item flexflex" v-for="(it,i) in item.data.offerlist" :key="i"> <div class="item-content flexflex"> <div class="school flexacenter"> <img class="icon" :src="it.schoollogo" mode="heightFix"></image> <div class="name one-line-display flex1">{{ it.schoolname }}</div> </div> <div class="major one-line-display" v-if="it.professional">{{ it.professional }}</div> <div class="info flexacenter"> {{ it.semester || '25Fall' }} <div class="line"></div> {{ it.degree || 'MSc' }} <div class="line"></div> <div class="results" :class="['r' + it.apply_results]">{{ it.apply_results_text || 'Offer' }}</div> </div> </div> </div> <div v-if="item.data.offercount > 3" class="item more flexcenter"> <div class="item-content flexcenter"> <div class="">查看更多</div> <img class="icon" src="/img/arrows-circle-dark-blue.svg" mode="heightFix"></image> </div> </div> </div> <item-bottom></item-bottom></div>`,
});

View File

@@ -0,0 +1,36 @@
<div class="item-box item-summary">
<item-head></item-head>
<div class="title" v-if="item.title">{{ item.title }}</div>
<div class="message one-line-display" v-if="item.content">{{ item.content }}</div>
<div class="total flexacenter">
<div>共</div>
<div class="num">{{ item.data.offercount }}</div>
<div>个Offer</div>
</div>
<div class="list flexacenter" scroll-x>
<div class="item flexflex" v-for="(it,i) in item.data.offerlist" :key="i">
<div class="item-content flexflex">
<div class="school flexacenter">
<img class="icon" :src="it.schoollogo" mode="heightFix"></image>
<div class="name one-line-display flex1">{{ it.schoolname }}</div>
</div>
<div class="major one-line-display" v-if="it.professional">{{ it.professional }}</div>
<div class="info flexacenter">
{{ it.semester || '25Fall' }}
<div class="line"></div>
{{ it.degree || 'MSc' }}
<div class="line"></div>
<div class="results" :class="['r' + it.apply_results]">{{ it.apply_results_text || 'Offer' }}</div>
</div>
</div>
</div>
<div v-if="item.data.offercount > 3" class="item more flexcenter">
<div class="item-content flexcenter">
<div class="">查看更多</div>
<img class="icon" src="/img/arrows-circle-dark-blue.svg" mode="heightFix"></image>
</div>
</div>
</div>
<item-bottom></item-bottom>
</div>

View File

@@ -0,0 +1,38 @@
// my-component.js
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入Vue 已挂载到 window
const { defineComponent, ref } = Vue;
import { itemBottom } from "../item-bottom/item-bottom.js";
import { itemHead } from "../item-head/item-head.js";
// 定义组件(直接使用模板)
export const itemVote = defineComponent({
name: "item-vote",
props: {
itemdata: {
type: Object,
default: () => {},
},
},
setup(props) {
let item = ref({ ...props.itemdata });
// item.value.title = "【投41票】" + item.value.title;
// res["timestamp"] = util.strtimeago(res.release_at, 4);
// const data = res.data;
// const option = data.option || [];
// res["isvote"] = option.some((item) => item.selected == 1);
// const time = util.handleDeadline(data.deadline);
// res["time"] = time;
// this.setData({
// item: res,
// });
return { item };
},
components: {
itemBottom,
itemHead,
},
template: `<div class="item-box item-vote"> <item-head :itemdata="item"></item-head> <div class="title">{{ item.title }}</div> <div class="message one-line-display" v-if="item.content">{{ item.content }}</div> <div class="info flexacenter"> <template v-if="item.time"> <div class="status">进行中</div> <div class="line"></div> <div class="num">{{ item?.time.num }}</div>{{ item.time.unit }}后结束 </template> <div v-else class="status end">已结束</div> <div class="line"></div> <div class="num">{{ item?.data?.votes }}</div>人参与 </div> <div class="list" :class="{ 'voted': !item.time || item.isvote }"> <div class="list-item flexcenter " v-for="(item, index) in item?.data?.option" :key="index"> <div class="list-top flexacenter"> <img v-if="item.selected" class="list-tick" src="/img/vote-tick.svg"> <div v-else class="list-serial flexcenter">{{ index + 1 }}</div> <div class="list-text one-line-display flex1">{{ item.value }}</div> </div> <div class="list-bottom flexacenter"> <div class="list-length" :style="{ width: item.percentage + '%' }"></div>{{ item.count }} </div> </div> </div> <item-bottom :itemdata="item"></item-bottom></div>`,
});

View File

@@ -0,0 +1,29 @@
<div class="item-box item-vote">
<item-head :itemdata="item"></item-head>
<div class="title">{{ item.title }}</div>
<div class="message one-line-display" v-if="item.content">{{ item.content }}</div>
<div class="info flexacenter">
<template v-if="item.time">
<div class="status">进行中</div>
<div class="line"></div>
<div class="num">{{ item?.time.num }}</div>{{ item.time.unit }}后结束
</template>
<div v-else class="status end">已结束</div>
<div class="line"></div>
<div class="num">{{ item?.data?.votes }}</div>人参与
</div>
<div class="list" :class="{ 'voted': !item.time || item.isvote }">
<div class="list-item flexcenter " v-for="(item, index) in item?.data?.option" :key="index">
<div class="list-top flexacenter">
<img v-if="item.selected" class="list-tick" src="/img/vote-tick.svg">
<div v-else class="list-serial flexcenter">{{ index + 1 }}</div>
<div class="list-text one-line-display flex1">{{ item.value }}</div>
</div>
<div class="list-bottom flexacenter">
<div class="list-length" :style="{ width: item.percentage + '%' }"></div>{{ item.count }}
</div>
</div>
</div>
<item-bottom :itemdata="item"></item-bottom>
</div>