= 职业规划推荐
This commit is contained in:
@@ -1,3 +0,0 @@
|
|||||||
export * from './career-recommendation.js';
|
|
||||||
export * from './career-path.js';
|
|
||||||
export * from './skill-development.js';
|
|
||||||
@@ -1,172 +1,15 @@
|
|||||||
<!--suppress JSFileReferences, NpmUsedModulesInstalled, VueMissingComponentImportInspection -->
|
<!--suppress JSFileReferences, NpmUsedModulesInstalled, VueMissingComponentImportInspection, HtmlUnknownTag -->
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, ref, watch } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useCareerRecommendationStore } from './store';
|
import { useCareerRecommendationStore } from '@/stores/useCareerRecommendationStore';
|
||||||
import { recommendJob } from '@/apiRc/service/jobRecommend.js';
|
import uniList from '@/uni_modules/uni-list/components/uni-list/uni-list.vue';
|
||||||
import { appUserInfo } from '@/apiRc/user/user.js';
|
import uniListItem from '@/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue';
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
currentJobId: {
|
|
||||||
type: [ Number, String ],
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
currentJobName: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const store = useCareerRecommendationStore();
|
const store = useCareerRecommendationStore();
|
||||||
|
|
||||||
const emit = defineEmits([ 'job-card-click', 'skills-updated' ]);
|
|
||||||
|
|
||||||
const popupRef = ref();
|
const popupRef = ref();
|
||||||
|
|
||||||
// 数据状态
|
|
||||||
const skillTags = ref([]);
|
|
||||||
const recommendedJobs = ref([]);
|
|
||||||
const isLoadingSkillTags = ref(false);
|
|
||||||
const isLoadingRecommend = ref(false);
|
|
||||||
|
|
||||||
// 计算属性
|
|
||||||
const currentJobDisplay = computed(() => props.currentJobName || '市场专员');
|
|
||||||
|
|
||||||
// 从 appSkillsList 中提取技能名称
|
|
||||||
function extractSkillsFromAppSkillsList(appSkillsList = []) {
|
|
||||||
return (Array.isArray(appSkillsList) ? appSkillsList : [])
|
|
||||||
.map(item => item?.name || item?.nameStr || '')
|
|
||||||
.filter(name => !!name && name.trim().length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从技能列表中提取技能名称用于显示(用于推荐职位数据)
|
|
||||||
function extractSkillNames(skillList = []) {
|
|
||||||
return (Array.isArray(skillList) ? skillList : [])
|
|
||||||
.map(item => item?.skillName || '')
|
|
||||||
.filter(name => !!name && name.trim().length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前职位的技能标签
|
|
||||||
async function fetchCurrentJobSkills() {
|
|
||||||
isLoadingSkillTags.value = true;
|
|
||||||
try {
|
|
||||||
// 优先从 appUserInfo 接口获取技能标签
|
|
||||||
const response = await appUserInfo();
|
|
||||||
const userInfo = response?.data || {};
|
|
||||||
|
|
||||||
// 从 appSkillsList 中提取技能名称
|
|
||||||
const appSkillsList = Array.isArray(userInfo?.appSkillsList) ? userInfo.appSkillsList : [];
|
|
||||||
const apiSkills = extractSkillsFromAppSkillsList(appSkillsList);
|
|
||||||
|
|
||||||
// 如果接口返回了技能数据,使用接口数据
|
|
||||||
if (apiSkills.length > 0) {
|
|
||||||
skillTags.value = apiSkills;
|
|
||||||
} else {
|
|
||||||
// 如果接口没有返回技能数据,从缓存中读取
|
|
||||||
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
|
|
||||||
const cachedAppSkills = Array.isArray(cachedUserInfo?.appSkillsList) ? cachedUserInfo.appSkillsList : [];
|
|
||||||
const cachedSkills = extractSkillsFromAppSkillsList(cachedAppSkills);
|
|
||||||
|
|
||||||
if (cachedSkills.length > 0) {
|
|
||||||
skillTags.value = cachedSkills;
|
|
||||||
} else {
|
|
||||||
skillTags.value = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通知父组件技能数据已更新
|
|
||||||
emit('skills-updated', {
|
|
||||||
currentJobSkills: skillTags.value,
|
|
||||||
recommendedJobs: recommendedJobs.value
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
// appUserInfo 接口调用失败时,从缓存中读取
|
|
||||||
const cachedUserInfo = uni.getStorageSync('userInfo') || {};
|
|
||||||
const cachedAppSkills = Array.isArray(cachedUserInfo?.appSkillsList) ? cachedUserInfo.appSkillsList : [];
|
|
||||||
const cachedSkills = extractSkillsFromAppSkillsList(cachedAppSkills);
|
|
||||||
|
|
||||||
if (cachedSkills.length > 0) {
|
|
||||||
skillTags.value = cachedSkills;
|
|
||||||
} else {
|
|
||||||
skillTags.value = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
emit('skills-updated', {
|
|
||||||
currentJobSkills: skillTags.value,
|
|
||||||
recommendedJobs: recommendedJobs.value
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
isLoadingSkillTags.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取推荐职位列表
|
|
||||||
async function fetchRecommendedJobs() {
|
|
||||||
isLoadingRecommend.value = true;
|
|
||||||
try {
|
|
||||||
const response = await recommendJob({
|
|
||||||
jobName: props.currentJobName
|
|
||||||
});
|
|
||||||
|
|
||||||
const list = Array.isArray(response?.data) ? response.data : [];
|
|
||||||
|
|
||||||
recommendedJobs.value = list.map((item, index) => {
|
|
||||||
const skillList = Array.isArray(item?.skillList) ? item.skillList : [];
|
|
||||||
const skillNames = extractSkillNames(skillList);
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: item?.jobId ?? index,
|
|
||||||
jobId: item?.jobId ?? null,
|
|
||||||
title: item?.jobName || `推荐职位${ index + 1 }`,
|
|
||||||
jobName: item?.jobName || '',
|
|
||||||
skills: skillNames,
|
|
||||||
rawSkills: skillList
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// 通知父组件推荐职位数据已更新
|
|
||||||
emit('skills-updated', {
|
|
||||||
currentJobSkills: skillTags.value,
|
|
||||||
recommendedJobs: recommendedJobs.value
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
recommendedJobs.value = [];
|
|
||||||
emit('skills-updated', {
|
|
||||||
currentJobSkills: skillTags.value,
|
|
||||||
recommendedJobs: []
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
isLoadingRecommend.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 组件挂载时检查并调用
|
|
||||||
onMounted(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (props.currentJobName) {
|
|
||||||
fetchCurrentJobSkills();
|
|
||||||
fetchRecommendedJobs();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听 props 变化,自动获取推荐职位和技能标签
|
|
||||||
watch(
|
|
||||||
() => [ props.currentJobId, props.currentJobName ],
|
|
||||||
() => {
|
|
||||||
if (props.currentJobName) {
|
|
||||||
fetchCurrentJobSkills();
|
|
||||||
fetchRecommendedJobs();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
// 事件处理
|
|
||||||
function handleJobCardClick(job) {
|
|
||||||
emit('job-card-click', job);
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventSelectCurrentJob = () => {
|
const eventSelectCurrentJob = () => {
|
||||||
popupRef.value?.open('bottom');
|
popupRef.value?.open('bottom');
|
||||||
};
|
};
|
||||||
@@ -174,52 +17,62 @@ const eventSelectCurrentJob = () => {
|
|||||||
const eventCloseCurrentJob = () => {
|
const eventCloseCurrentJob = () => {
|
||||||
popupRef.value?.close('bottom');
|
popupRef.value?.close('bottom');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const eventProfession = (item) => {
|
||||||
|
store.eventProfession(item);
|
||||||
|
store.eventSearch();
|
||||||
|
popupRef.value?.close('bottom');
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="career-recommend">
|
<div class="career-recommend">
|
||||||
<!-- 当前职位信息卡片 -->
|
|
||||||
<div class="info-card">
|
<div class="info-card">
|
||||||
<div class="card-title">当前职位信息</div>
|
<div class="card-title">当前职位信息</div>
|
||||||
<div class="card-content">
|
<div class="card-content" @click="eventSelectCurrentJob">
|
||||||
<span class="label">当前职位</span>
|
<span class="label">当前职位</span> <span class="value">{{ store.professionLabel }}</span>
|
||||||
<span class="value" @click="eventSelectCurrentJob">{{ currentJobDisplay }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 我的技能标签卡片 -->
|
|
||||||
<div class="info-card">
|
<div class="info-card">
|
||||||
<div class="card-title">我的技能标签</div>
|
<div class="card-title">我的技能标签</div>
|
||||||
<div class="skill-tags">
|
<div class="skill-tags">
|
||||||
<div v-for="(skill, index) in skillTags" :key="index" class="skill-tag">
|
<div v-for="(skill, index) in store.skillTags" :key="index" class="skill-tag">
|
||||||
{{ skill }}
|
{{ skill }}
|
||||||
</div>
|
</div>
|
||||||
<span v-if="!skillTags.length && !isLoadingSkillTags" class="empty-text">暂无技能数据</span>
|
<span v-if="!store.skillTags.length" class="empty-text">暂无技能数据</span>
|
||||||
<span v-if="isLoadingSkillTags" class="empty-text">加载中...</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 相似推荐职位 -->
|
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
相似推荐职位
|
相似推荐职位
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!isLoadingRecommend && recommendedJobs.length === 0" class="empty-text">暂无推荐职位</div>
|
<div v-if="!store.result && store.result.length === 0" class="empty-text">暂无推荐职位</div>
|
||||||
<div v-for="(job, index) in recommendedJobs" :key="index" class="job-item-card" @click="handleJobCardClick(job)">
|
<div v-for="(job, index) in store.result" :key="index" class="job-item-card">
|
||||||
<div class="job-header">
|
<div class="job-header">
|
||||||
<span class="job-title">{{ job.title }}</span>
|
<span class="job-title">{{ job.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="job-header">
|
||||||
|
<span>职业相似度:{{ job.percentage }}%</span>
|
||||||
|
</div>
|
||||||
<div class="job-skills">
|
<div class="job-skills">
|
||||||
<div v-for="(skill, skillIndex) in job.skills" :key="skillIndex" class="job-skill-tag">
|
<div v-for="tag in job.tags" :key="tag" class="job-skill-tag">
|
||||||
{{ skill }}
|
{{ tag }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<uni-popup ref="popupRef" :border-radius="'20rpx 20rpx 0 0'" :is-mask-click="true" background-color="#FFFFFF" mask-background-color="rgba(255, 255, 255, 0.6)" type="bottom" @mask-click="eventCloseCurrentJob">
|
||||||
|
<div class="professions">
|
||||||
|
<scroll-view scroll-y style="height: 100%;">
|
||||||
|
<div class="professions-list">
|
||||||
|
<uni-list>
|
||||||
|
<template v-for="item in store.professionsRef" :key="item.label">
|
||||||
|
<uni-list-item :title="item.label" clickable showArrow @click="eventProfession(item)" />
|
||||||
|
</template>
|
||||||
|
</uni-list>
|
||||||
|
</div>
|
||||||
|
</scroll-view>
|
||||||
|
</div>
|
||||||
|
</uni-popup>
|
||||||
</div>
|
</div>
|
||||||
<uni-popup ref="popupRef" :border-radius="'20rpx 20rpx 0 0'" :is-mask-click="true" background-color="#FFFFFF" mask-background-color="rgba(255, 255, 255, 0.6)" type="bottom" @mask-click="eventCloseCurrentJob">
|
|
||||||
<div class="">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</uni-popup>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -297,7 +150,6 @@ const eventCloseCurrentJob = () => {
|
|||||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||||
border-left: 6rpx solid #409EFF;
|
border-left: 6rpx solid #409EFF;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.job-header {
|
.job-header {
|
||||||
@@ -354,4 +206,13 @@ const eventCloseCurrentJob = () => {
|
|||||||
button::after {
|
button::after {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.professions {
|
||||||
|
width: 100vw;
|
||||||
|
height: 80vh;
|
||||||
|
|
||||||
|
.professions-list {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
export * from './user';
|
|
||||||
export * from './career-recommendation';
|
|
||||||
export * from './career-path';
|
|
||||||
export * from './skill-development';
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import { ref } from 'vue';
|
|
||||||
import { defineStore } from 'pinia';
|
|
||||||
import { getUserInfo, getUserName } from '@/apiRc/service';
|
|
||||||
|
|
||||||
export const useAuthUserStore = defineStore('auth-user', () => {
|
|
||||||
const token = ref('');
|
|
||||||
|
|
||||||
const userLoaded = ref(false);
|
|
||||||
|
|
||||||
const userInfoRef = ref({
|
|
||||||
userName: '',
|
|
||||||
professions: [],
|
|
||||||
skills: []
|
|
||||||
});
|
|
||||||
|
|
||||||
const fetchUserInfo = async () => {
|
|
||||||
const tokenA = await $getItem('tokenA');
|
|
||||||
const cryptogram = await $getItem('cryptogram');
|
|
||||||
if (!cryptogram) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
token.value = cryptogram;
|
|
||||||
try {
|
|
||||||
const { code, msg, data } = await getUserInfo(cryptogram);
|
|
||||||
if (code !== 200) {
|
|
||||||
$emitter.emit('error-message', msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
userInfoRef.value.professions = data.jobTitles.map((d) => {
|
|
||||||
return {
|
|
||||||
label: d,
|
|
||||||
value: d
|
|
||||||
};
|
|
||||||
});
|
|
||||||
userInfoRef.value.skills = data.appSkillsList.map((d) => {
|
|
||||||
return {
|
|
||||||
label: d.name,
|
|
||||||
value: d.name
|
|
||||||
};
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const { code: c, msg: m, data: userName } = await getUserName({ accessToken: tokenA });
|
|
||||||
if (c !== 0 || !userName) {
|
|
||||||
$emitter.emit('error-message', m);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
userInfoRef.value.userName = userName.name;
|
|
||||||
userLoaded.value = true;
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
token,
|
|
||||||
userInfo: userInfoRef,
|
|
||||||
userLoaded,
|
|
||||||
fetchUserInfo
|
|
||||||
};
|
|
||||||
});
|
|
||||||
@@ -1,21 +1,42 @@
|
|||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { useBasicStore, useAuthUserStore } from './index';
|
import { getProfessions, getSkillTags, getRecommend } from '@/apiRc/service/careerRecommendation';
|
||||||
import { getProfessions, getSkillTags, getRecommend } from '@/apiRc/service';
|
|
||||||
|
|
||||||
export const useCareerRecommendationStore = defineStore('career-recommendation', () => {
|
export const useCareerRecommendationStore = defineStore('career-recommendation', () => {
|
||||||
const storeBasic = useBasicStore();
|
const userInfo = ref({
|
||||||
const storeUser = useAuthUserStore();
|
userName: '',
|
||||||
|
professions: [],
|
||||||
|
skills: []
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = uni.getStorageSync('userInfo');
|
||||||
|
|
||||||
|
userInfo.value.professions = data.jobTitle.map((d) => {
|
||||||
|
return {
|
||||||
|
label: d,
|
||||||
|
value: d
|
||||||
|
};
|
||||||
|
});
|
||||||
|
userInfo.value.skills = data.appSkillsList.map((d) => {
|
||||||
|
return {
|
||||||
|
label: d.name,
|
||||||
|
value: d.name
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(e);
|
||||||
|
}
|
||||||
|
|
||||||
const profession = ref('');
|
const profession = ref('');
|
||||||
|
const professionLabel = ref('');
|
||||||
const professions = ref([]);
|
const professions = ref([]);
|
||||||
|
|
||||||
const professionsRef = computed(() => {
|
const professionsRef = computed(() => {
|
||||||
const userInfo = storeUser.userInfo;
|
if (!userInfo.value || !userInfo.value.professions || userInfo.value.professions.length === 0) {
|
||||||
if (!userInfo || !userInfo.professions || userInfo.professions.length === 0) {
|
|
||||||
return professions.value;
|
return professions.value;
|
||||||
}
|
}
|
||||||
const userProfessionsLabels = userInfo.professions.map((d) => d.label);
|
const userProfessionsLabels = userInfo.value.professions.map((d) => d.label);
|
||||||
let professionsA = [];
|
let professionsA = [];
|
||||||
let professionsB = [];
|
let professionsB = [];
|
||||||
professions.value.filter((d) => userProfessionsLabels.includes(d.label));
|
professions.value.filter((d) => userProfessionsLabels.includes(d.label));
|
||||||
@@ -27,18 +48,16 @@ export const useCareerRecommendationStore = defineStore('career-recommendation',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (professionsA.length === 0) {
|
if (professionsA.length === 0) {
|
||||||
professionsA = userInfo.professions;
|
professionsA = userInfo.value.professions;
|
||||||
professionsB = professions.value;
|
professionsB = professions.value;
|
||||||
}
|
}
|
||||||
return [...professionsA, ...professionsB];
|
return [...professionsA, ...professionsB];
|
||||||
});
|
});
|
||||||
|
|
||||||
const skills = ref([]);
|
const skills = ref([]);
|
||||||
|
|
||||||
const skillTags = computed(() => {
|
const skillTags = computed(() => {
|
||||||
const userInfo = storeUser.userInfo;
|
if (userInfo.value.professions[0] && professionLabel.value === userInfo.value.professions[0].value) {
|
||||||
if (userInfo.professions[0] && profession.value === userInfo.professions[0].value) {
|
return userInfo.value.skills.map((d) => d.label);
|
||||||
return userInfo.skills.map((d) => d.label);
|
|
||||||
}
|
}
|
||||||
return skills.value;
|
return skills.value;
|
||||||
});
|
});
|
||||||
@@ -68,7 +87,7 @@ export const useCareerRecommendationStore = defineStore('career-recommendation',
|
|||||||
|
|
||||||
const fetchSkillTags = async () => {
|
const fetchSkillTags = async () => {
|
||||||
const params = {
|
const params = {
|
||||||
jobName: profession.value
|
jobName: professionLabel.value
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const { code, msg, data } = await getSkillTags(params);
|
const { code, msg, data } = await getSkillTags(params);
|
||||||
@@ -86,7 +105,7 @@ export const useCareerRecommendationStore = defineStore('career-recommendation',
|
|||||||
|
|
||||||
const fetchRecommend = async () => {
|
const fetchRecommend = async () => {
|
||||||
const params = {
|
const params = {
|
||||||
jobName: profession.value
|
jobName: professionLabel.value
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
const { code, msg, data } = await getRecommend(params);
|
const { code, msg, data } = await getRecommend(params);
|
||||||
@@ -109,24 +128,23 @@ export const useCareerRecommendationStore = defineStore('career-recommendation',
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const eventProfession = (item) => {
|
||||||
|
profession.value = item.value;
|
||||||
|
professionLabel.value = item.label;
|
||||||
|
}
|
||||||
|
|
||||||
const eventSearch = () => {
|
const eventSearch = () => {
|
||||||
void fetchRecommend();
|
void fetchRecommend();
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
|
||||||
() => storeBasic.loaded,
|
|
||||||
() => {
|
|
||||||
if (storeBasic.loaded) {
|
|
||||||
void fetchData();
|
void fetchData();
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => profession.value,
|
() => profession.value,
|
||||||
() => {
|
() => {
|
||||||
if (profession.value) {
|
if (profession.value) {
|
||||||
void fetchSkillTags();
|
void fetchSkillTags();
|
||||||
|
eventSearch();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -138,17 +156,20 @@ export const useCareerRecommendationStore = defineStore('career-recommendation',
|
|||||||
() => professionsRef.value,
|
() => professionsRef.value,
|
||||||
() => {
|
() => {
|
||||||
if (professionsRef.value[0]) {
|
if (professionsRef.value[0]) {
|
||||||
profession.value = professionsRef.value[0].label;
|
profession.value = professionsRef.value[0].value;
|
||||||
|
professionLabel.value = professionsRef.value[0].label;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
profession,
|
profession,
|
||||||
|
professionLabel,
|
||||||
professions,
|
professions,
|
||||||
professionsRef,
|
professionsRef,
|
||||||
skillTags,
|
skillTags,
|
||||||
result,
|
result,
|
||||||
eventSearch
|
eventSearch,
|
||||||
|
eventProfession
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
33
uni_modules/uni-badge/changelog.md
Normal file
33
uni_modules/uni-badge/changelog.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
## 1.2.2(2023-01-28)
|
||||||
|
- 修复 运行/打包 控制台警告问题
|
||||||
|
## 1.2.1(2022-09-05)
|
||||||
|
- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
|
||||||
|
## 1.2.0(2021-11-19)
|
||||||
|
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||||
|
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
|
||||||
|
## 1.1.7(2021-11-08)
|
||||||
|
- 优化 升级ui
|
||||||
|
- 修改 size 属性默认值调整为 small
|
||||||
|
- 修改 type 属性,默认值调整为 error,info 替换 default
|
||||||
|
## 1.1.6(2021-09-22)
|
||||||
|
- 修复 在字节小程序上样式不生效的 bug
|
||||||
|
## 1.1.5(2021-07-30)
|
||||||
|
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||||
|
## 1.1.4(2021-07-29)
|
||||||
|
- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
|
||||||
|
## 1.1.3(2021-06-24)
|
||||||
|
- 优化 示例项目
|
||||||
|
## 1.1.1(2021-05-12)
|
||||||
|
- 新增 组件示例地址
|
||||||
|
## 1.1.0(2021-05-12)
|
||||||
|
- 新增 uni-badge 的 absolute 属性,支持定位
|
||||||
|
- 新增 uni-badge 的 offset 属性,支持定位偏移
|
||||||
|
- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
|
||||||
|
- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
|
||||||
|
- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
|
||||||
|
## 1.0.7(2021-05-07)
|
||||||
|
- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
|
||||||
|
- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
|
||||||
|
- 新增 uni-badge 属性 custom-style, 支持自定义样式
|
||||||
|
## 1.0.6(2021-02-04)
|
||||||
|
- 调整为uni_modules目录规范
|
||||||
268
uni_modules/uni-badge/components/uni-badge/uni-badge.vue
Normal file
268
uni_modules/uni-badge/components/uni-badge/uni-badge.vue
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
<template>
|
||||||
|
<view class="uni-badge--x">
|
||||||
|
<slot />
|
||||||
|
<text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
|
||||||
|
class="uni-badge" @click="onClick()">{{displayValue}}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* Badge 数字角标
|
||||||
|
* @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=21
|
||||||
|
* @property {String} text 角标内容
|
||||||
|
* @property {String} size = [normal|small] 角标内容
|
||||||
|
* @property {String} type = [info|primary|success|warning|error] 颜色类型
|
||||||
|
* @value info 灰色
|
||||||
|
* @value primary 蓝色
|
||||||
|
* @value success 绿色
|
||||||
|
* @value warning 黄色
|
||||||
|
* @value error 红色
|
||||||
|
* @property {String} inverted = [true|false] 是否无需背景颜色
|
||||||
|
* @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
|
||||||
|
* @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
|
||||||
|
* @value rightTop 右上
|
||||||
|
* @value rightBottom 右下
|
||||||
|
* @value leftTop 左上
|
||||||
|
* @value leftBottom 左下
|
||||||
|
* @property {Array[number]} offset 距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
|
||||||
|
* @property {String} isDot = [true|false] 是否显示为一个小点
|
||||||
|
* @event {Function} click 点击 Badge 触发事件
|
||||||
|
* @example <uni-badge text="1"></uni-badge>
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'UniBadge',
|
||||||
|
emits: ['click'],
|
||||||
|
props: {
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'error'
|
||||||
|
},
|
||||||
|
inverted: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
isDot: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
maxNum: {
|
||||||
|
type: Number,
|
||||||
|
default: 99
|
||||||
|
},
|
||||||
|
absolute: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
offset: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return [0, 0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: 'small'
|
||||||
|
},
|
||||||
|
customStyle: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
width() {
|
||||||
|
return String(this.text).length * 8 + 12
|
||||||
|
},
|
||||||
|
classNames() {
|
||||||
|
const {
|
||||||
|
inverted,
|
||||||
|
type,
|
||||||
|
size,
|
||||||
|
absolute
|
||||||
|
} = this
|
||||||
|
return [
|
||||||
|
inverted ? 'uni-badge--' + type + '-inverted' : '',
|
||||||
|
'uni-badge--' + type,
|
||||||
|
'uni-badge--' + size,
|
||||||
|
absolute ? 'uni-badge--absolute' : ''
|
||||||
|
].join(' ')
|
||||||
|
},
|
||||||
|
positionStyle() {
|
||||||
|
if (!this.absolute) return {}
|
||||||
|
let w = this.width / 2,
|
||||||
|
h = 10
|
||||||
|
if (this.isDot) {
|
||||||
|
w = 5
|
||||||
|
h = 5
|
||||||
|
}
|
||||||
|
const x = `${- w + this.offset[0]}px`
|
||||||
|
const y = `${- h + this.offset[1]}px`
|
||||||
|
|
||||||
|
const whiteList = {
|
||||||
|
rightTop: {
|
||||||
|
right: x,
|
||||||
|
top: y
|
||||||
|
},
|
||||||
|
rightBottom: {
|
||||||
|
right: x,
|
||||||
|
bottom: y
|
||||||
|
},
|
||||||
|
leftBottom: {
|
||||||
|
left: x,
|
||||||
|
bottom: y
|
||||||
|
},
|
||||||
|
leftTop: {
|
||||||
|
left: x,
|
||||||
|
top: y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const match = whiteList[this.absolute]
|
||||||
|
return match ? match : whiteList['rightTop']
|
||||||
|
},
|
||||||
|
dotStyle() {
|
||||||
|
if (!this.isDot) return {}
|
||||||
|
return {
|
||||||
|
width: '10px',
|
||||||
|
minWidth: '0',
|
||||||
|
height: '10px',
|
||||||
|
padding: '0',
|
||||||
|
borderRadius: '10px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
displayValue() {
|
||||||
|
const {
|
||||||
|
isDot,
|
||||||
|
text,
|
||||||
|
maxNum
|
||||||
|
} = this
|
||||||
|
return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onClick() {
|
||||||
|
this.$emit('click');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" >
|
||||||
|
$uni-primary: #2979ff !default;
|
||||||
|
$uni-success: #4cd964 !default;
|
||||||
|
$uni-warning: #f0ad4e !default;
|
||||||
|
$uni-error: #dd524d !default;
|
||||||
|
$uni-info: #909399 !default;
|
||||||
|
|
||||||
|
|
||||||
|
$bage-size: 12px;
|
||||||
|
$bage-small: scale(0.8);
|
||||||
|
|
||||||
|
.uni-badge--x {
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
// align-self: flex-start;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: inline-block;
|
||||||
|
/* #endif */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge--absolute {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge--small {
|
||||||
|
transform: $bage-small;
|
||||||
|
transform-origin: center center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-feature-settings: "tnum";
|
||||||
|
min-width: 20px;
|
||||||
|
/* #endif */
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 20px;
|
||||||
|
padding: 0 4px;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 100px;
|
||||||
|
background-color: $uni-info;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
text-align: center;
|
||||||
|
font-family: 'Helvetica Neue', Helvetica, sans-serif;
|
||||||
|
font-size: $bage-size;
|
||||||
|
/* #ifdef H5 */
|
||||||
|
z-index: 999;
|
||||||
|
cursor: pointer;
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
&--info {
|
||||||
|
color: #fff;
|
||||||
|
background-color: $uni-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--primary {
|
||||||
|
background-color: $uni-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success {
|
||||||
|
background-color: $uni-success;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning {
|
||||||
|
background-color: $uni-warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error {
|
||||||
|
background-color: $uni-error;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--inverted {
|
||||||
|
padding: 0 5px 0 0;
|
||||||
|
color: $uni-info;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--info-inverted {
|
||||||
|
color: $uni-info;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--primary-inverted {
|
||||||
|
color: $uni-primary;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--success-inverted {
|
||||||
|
color: $uni-success;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--warning-inverted {
|
||||||
|
color: $uni-warning;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--error-inverted {
|
||||||
|
color: $uni-error;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
85
uni_modules/uni-badge/package.json
Normal file
85
uni_modules/uni-badge/package.json
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"id": "uni-badge",
|
||||||
|
"displayName": "uni-badge 数字角标",
|
||||||
|
"version": "1.2.2",
|
||||||
|
"description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
|
||||||
|
"keywords": [
|
||||||
|
"",
|
||||||
|
"badge",
|
||||||
|
"uni-ui",
|
||||||
|
"uniui",
|
||||||
|
"数字角标",
|
||||||
|
"徽章"
|
||||||
|
],
|
||||||
|
"repository": "https://github.com/dcloudio/uni-ui",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": ""
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"example": "../../temps/example_temps"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||||
|
"type": "component-vue"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": ["uni-scss"],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "y",
|
||||||
|
"联盟": "y"
|
||||||
|
},
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
uni_modules/uni-badge/readme.md
Normal file
10
uni_modules/uni-badge/readme.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
## Badge 数字角标
|
||||||
|
> **组件名:uni-badge**
|
||||||
|
> 代码块: `uBadge`
|
||||||
|
|
||||||
|
数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
|
||||||
|
|
||||||
|
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge)
|
||||||
|
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||||
|
|
||||||
|
|
||||||
52
uni_modules/uni-list/changelog.md
Normal file
52
uni_modules/uni-list/changelog.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
## 1.2.17(2025-08-20)
|
||||||
|
- 修复 右侧箭头类型错误的问题
|
||||||
|
## 1.2.16(2025-04-14)
|
||||||
|
- 修复 可触发点击反馈的 uni-list-item 没有hover效果的问题
|
||||||
|
## 1.2.15(2025-01-08)
|
||||||
|
- 修复 示例中过期图片地址
|
||||||
|
## 1.2.14(2023-04-14)
|
||||||
|
- 优化 uni-list-chat 具名插槽`header` 非app端套一层元素,方便使用时通过外层元素定位实现样式修改
|
||||||
|
## 1.2.13(2023-03-03)
|
||||||
|
- uni-list-chat 新增 支持具名插槽`header`
|
||||||
|
## 1.2.12(2023-02-01)
|
||||||
|
- 新增 列表图标新增 customPrefix 属性 ,用法 [详见](https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html#icons-props)
|
||||||
|
## 1.2.11(2023-01-31)
|
||||||
|
- 修复 无反馈效果呈现的bug
|
||||||
|
## 1.2.9(2022-11-22)
|
||||||
|
- 修复 uni-list-chat 在vue3下跳转报错的bug
|
||||||
|
## 1.2.8(2022-11-21)
|
||||||
|
- 修复 uni-list-chat avatar属性 值为本地路径时错误的问题
|
||||||
|
## 1.2.7(2022-11-21)
|
||||||
|
- 修复 uni-list-chat avatar属性 在腾讯云版uniCloud下错误的问题
|
||||||
|
## 1.2.6(2022-11-18)
|
||||||
|
- 修复 uni-list-chat note属性 支持:“草稿”字样功能 文本少1位的问题
|
||||||
|
## 1.2.5(2022-11-15)
|
||||||
|
- 修复 uni-list-item 的 customStyle 属性 padding值在 H5端 无效的bug
|
||||||
|
## 1.2.4(2022-11-15)
|
||||||
|
- 修复 uni-list-item 的 customStyle 属性 padding值在nvue(vue2)下无效的bug
|
||||||
|
## 1.2.3(2022-11-14)
|
||||||
|
- uni-list-chat 新增 avatar 支持 fileId
|
||||||
|
## 1.2.2(2022-11-11)
|
||||||
|
- uni-list 新增属性 render-reverse 详情参考:[https://uniapp.dcloud.net.cn/component/list.html](https://uniapp.dcloud.net.cn/component/list.html)
|
||||||
|
- uni-list-chat note属性 支持:“草稿”字样 加红显示 详情参考uni-im:[https://ext.dcloud.net.cn/plugin?name=uni-im](https://ext.dcloud.net.cn/plugin?name=uni-im)
|
||||||
|
- uni-list-item 新增属性 customStyle 支持设置padding、backgroundColor
|
||||||
|
## 1.2.1(2022-03-30)
|
||||||
|
- 删除无用文件
|
||||||
|
## 1.2.0(2021-11-23)
|
||||||
|
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
|
||||||
|
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list)
|
||||||
|
## 1.1.3(2021-08-30)
|
||||||
|
- 修复 在vue3中to属性在发行应用的时候报错的bug
|
||||||
|
## 1.1.2(2021-07-30)
|
||||||
|
- 优化 vue3下事件警告的问题
|
||||||
|
## 1.1.1(2021-07-21)
|
||||||
|
- 修复 与其他组件嵌套使用时,点击失效的Bug
|
||||||
|
## 1.1.0(2021-07-13)
|
||||||
|
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
|
||||||
|
## 1.0.17(2021-05-12)
|
||||||
|
- 新增 组件示例地址
|
||||||
|
## 1.0.16(2021-02-05)
|
||||||
|
- 优化 组件引用关系,通过uni_modules引用组件
|
||||||
|
## 1.0.15(2021-02-05)
|
||||||
|
- 调整为uni_modules目录规范
|
||||||
|
- 修复 uni-list-chat 角标显示不正常的问题
|
||||||
107
uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
Normal file
107
uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<cell>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view class="uni-list-ad">
|
||||||
|
<view v-if="borderShow" :class="{'uni-list--border':border,'uni-list-item--first':isFirstChild}"></view>
|
||||||
|
<ad style="width: 200px;height: 300px;border-width: 1px;border-color: red;border-style: solid;" adpid="1111111111"
|
||||||
|
unit-id="" appid="" apid="" type="feed" @error="aderror" @close="closeAd"></ad>
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
</cell>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const dom = uni.requireNativePlugin('dom');
|
||||||
|
// #endif
|
||||||
|
export default {
|
||||||
|
name: 'UniListAd',
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// inject: ['list'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isFirstChild: false,
|
||||||
|
border: false,
|
||||||
|
borderShow: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.list = this.getForm()
|
||||||
|
if (this.list) {
|
||||||
|
if (!this.list.firstChildAppend) {
|
||||||
|
this.list.firstChildAppend = true
|
||||||
|
this.isFirstChild = true
|
||||||
|
}
|
||||||
|
this.border = this.list.border
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 获取父元素实例
|
||||||
|
*/
|
||||||
|
getForm(name = 'uniList') {
|
||||||
|
let parent = this.$parent;
|
||||||
|
let parentName = parent.$options.name;
|
||||||
|
while (parentName !== name) {
|
||||||
|
parent = parent.$parent;
|
||||||
|
if (!parent) return false
|
||||||
|
parentName = parent.$options.name;
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
},
|
||||||
|
aderror(e) {
|
||||||
|
console.log("aderror: " + JSON.stringify(e.detail));
|
||||||
|
},
|
||||||
|
closeAd(e) {
|
||||||
|
this.borderShow = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" >
|
||||||
|
.uni-list-ad {
|
||||||
|
position: relative;
|
||||||
|
border: 1px red solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list--border {
|
||||||
|
position: relative;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
/* #ifdef APP-PLUS */
|
||||||
|
border-top-color: $uni-border-color;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 0.5px;
|
||||||
|
/* #endif */
|
||||||
|
margin-left: $uni-spacing-row-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
.uni-list--border:after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
-webkit-transform: scaleY(.5);
|
||||||
|
transform: scaleY(.5);
|
||||||
|
background-color: $uni-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item--first:after {
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* 这里是 uni-list 组件内置的常用样式变量
|
||||||
|
* 如果需要覆盖样式,这里提供了基本的组件样式变量,您可以尝试修改这里的变量,去完成样式替换,而不用去修改源码
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 背景色
|
||||||
|
$background-color : #fff;
|
||||||
|
// 分割线颜色
|
||||||
|
$divide-line-color : #e5e5e5;
|
||||||
|
|
||||||
|
// 默认头像大小,如需要修改此值,注意同步修改 js 中的值 const avatarWidth = xx ,目前只支持方形头像
|
||||||
|
// nvue 页面不支持修改头像大小
|
||||||
|
$avatar-width : 45px ;
|
||||||
|
|
||||||
|
// 头像边框
|
||||||
|
$avatar-border-radius: 5px;
|
||||||
|
$avatar-border-color: #eee;
|
||||||
|
$avatar-border-width: 1px;
|
||||||
|
|
||||||
|
// 标题文字样式
|
||||||
|
$title-size : 16px;
|
||||||
|
$title-color : #3b4144;
|
||||||
|
$title-weight : normal;
|
||||||
|
|
||||||
|
// 描述文字样式
|
||||||
|
$note-size : 12px;
|
||||||
|
$note-color : #999;
|
||||||
|
$note-weight : normal;
|
||||||
|
|
||||||
|
// 右侧额外内容默认样式
|
||||||
|
$right-text-size : 12px;
|
||||||
|
$right-text-color : #999;
|
||||||
|
$right-text-weight : normal;
|
||||||
|
|
||||||
|
// 角标样式
|
||||||
|
// nvue 页面不支持修改圆点位置以及大小
|
||||||
|
// 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动
|
||||||
|
$badge-left: 0px;
|
||||||
|
$badge-top: 0px;
|
||||||
|
|
||||||
|
// 显示圆点时,圆点大小
|
||||||
|
$dot-width: 10px;
|
||||||
|
$dot-height: 10px;
|
||||||
|
|
||||||
|
// 显示角标时,角标大小和字体大小
|
||||||
|
$badge-size : 18px;
|
||||||
|
$badge-font : 12px;
|
||||||
|
// 显示角标时,角标前景色
|
||||||
|
$badge-color : #fff;
|
||||||
|
// 显示角标时,角标背景色
|
||||||
|
$badge-background-color : #ff5a5f;
|
||||||
|
// 显示角标时,角标左右间距
|
||||||
|
$badge-space : 6px;
|
||||||
|
|
||||||
|
// 状态样式
|
||||||
|
// 选中颜色
|
||||||
|
$hover : #f5f5f5;
|
||||||
593
uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
Normal file
593
uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
Normal file
@@ -0,0 +1,593 @@
|
|||||||
|
<template>
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<cell>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view :hover-class="!clickable && !link ? '' : 'uni-list-chat--hover'" class="uni-list-chat" @click.stop="onClick">
|
||||||
|
<view :class="{ 'uni-list--border': border, 'uni-list-chat--first': isFirstChild }"></view>
|
||||||
|
<view class="uni-list-chat__container">
|
||||||
|
<view class="uni-list-chat__header-warp">
|
||||||
|
<view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
|
||||||
|
<image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatarUrl" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
<!-- 头像组 -->
|
||||||
|
<view v-else class="uni-list-chat__header">
|
||||||
|
<view v-for="(item, index) in avatarList" :key="index" class="uni-list-chat__header-box" :class="computedAvatar"
|
||||||
|
:style="{ width: imageWidth + 'px', height: imageWidth + 'px' }">
|
||||||
|
<image class="uni-list-chat__header-image" :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }" :src="item.url"
|
||||||
|
mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #ifndef APP -->
|
||||||
|
<view class="slot-header">
|
||||||
|
<!-- #endif -->
|
||||||
|
<slot name="header"></slot>
|
||||||
|
<!-- #ifndef APP -->
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view v-if="badgeText && badgePositon === 'left'" class="uni-list-chat__badge uni-list-chat__badge-pos" :class="[isSingle]">
|
||||||
|
<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="uni-list-chat__content">
|
||||||
|
<view class="uni-list-chat__content-main">
|
||||||
|
<text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text>
|
||||||
|
<view style="flex-direction: row;">
|
||||||
|
<text class="draft" v-if="isDraft">[草稿]</text>
|
||||||
|
<text class="uni-list-chat__content-note uni-ellipsis">{{isDraft?note.slice(14):note}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="uni-list-chat__content-extra">
|
||||||
|
<slot>
|
||||||
|
<text class="uni-list-chat__content-extra-text">{{ time }}</text>
|
||||||
|
<view v-if="badgeText && badgePositon === 'right'" class="uni-list-chat__badge" :class="[isSingle, badgePositon === 'right' ? 'uni-list-chat--right' : '']">
|
||||||
|
<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
|
||||||
|
</view>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
</cell>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 头像大小
|
||||||
|
const avatarWidth = 45;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ListChat 聊天列表
|
||||||
|
* @description 聊天列表,用于创建聊天类列表
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||||
|
* @property {String} title 标题
|
||||||
|
* @property {String} note 描述
|
||||||
|
* @property {Boolean} clickable = [true|false] 是否开启点击反馈,默认为false
|
||||||
|
* @property {String} badgeText 数字角标内容
|
||||||
|
* @property {String} badgePositon = [left|right] 角标位置,默认为 right
|
||||||
|
* @property {String} link = [false|navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈,默认为false
|
||||||
|
* @value false 不开启
|
||||||
|
* @value navigateTo 同 uni.navigateTo()
|
||||||
|
* @value redirectTo 同 uni.redirectTo()
|
||||||
|
* @value reLaunch 同 uni.reLaunch()
|
||||||
|
* @value switchTab 同 uni.switchTab()
|
||||||
|
* @property {String | PageURIString} to 跳转目标页面
|
||||||
|
* @property {String} time 右侧时间显示
|
||||||
|
* @property {Boolean} avatarCircle = [true|false] 是否显示圆形头像,默认为false
|
||||||
|
* @property {String} avatar 头像地址,avatarCircle 不填时生效
|
||||||
|
* @property {Array} avatarList 头像组,格式为 [{url:''}]
|
||||||
|
* @event {Function} click 点击 uniListChat 触发事件
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'UniListChat',
|
||||||
|
emits:['click'],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
clickable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
badgeText: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
badgePositon: {
|
||||||
|
type: String,
|
||||||
|
default: 'right'
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
avatarCircle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
avatar: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
avatarList: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// inject: ['list'],
|
||||||
|
computed: {
|
||||||
|
isDraft(){
|
||||||
|
return this.note.slice(0,14) == '[uni-im-draft]'
|
||||||
|
},
|
||||||
|
isSingle() {
|
||||||
|
if (this.badgeText === 'dot') {
|
||||||
|
return 'uni-badge--dot';
|
||||||
|
} else {
|
||||||
|
const badgeText = this.badgeText.toString();
|
||||||
|
if (badgeText.length > 1) {
|
||||||
|
return 'uni-badge--complex';
|
||||||
|
} else {
|
||||||
|
return 'uni-badge--single';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computedAvatar() {
|
||||||
|
if (this.avatarList.length > 4) {
|
||||||
|
this.imageWidth = avatarWidth * 0.31;
|
||||||
|
return 'avatarItem--3';
|
||||||
|
} else if (this.avatarList.length > 1) {
|
||||||
|
this.imageWidth = avatarWidth * 0.47;
|
||||||
|
return 'avatarItem--2';
|
||||||
|
} else {
|
||||||
|
this.imageWidth = avatarWidth;
|
||||||
|
return 'avatarItem--1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
avatar:{
|
||||||
|
handler(avatar) {
|
||||||
|
if(avatar.substr(0,8) == 'cloud://'){
|
||||||
|
uniCloud.getTempFileURL({
|
||||||
|
fileList: [avatar]
|
||||||
|
}).then(res=>{
|
||||||
|
// console.log(res);
|
||||||
|
// 兼容uniCloud私有化部署
|
||||||
|
let fileList = res.fileList || res.result.fileList
|
||||||
|
this.avatarUrl = fileList[0].tempFileURL
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
this.avatarUrl = avatar
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isFirstChild: false,
|
||||||
|
border: true,
|
||||||
|
// avatarList: 3,
|
||||||
|
imageWidth: 50,
|
||||||
|
avatarUrl:''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.list = this.getForm()
|
||||||
|
if (this.list) {
|
||||||
|
if (!this.list.firstChildAppend) {
|
||||||
|
this.list.firstChildAppend = true;
|
||||||
|
this.isFirstChild = true;
|
||||||
|
}
|
||||||
|
this.border = this.list.border;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 获取父元素实例
|
||||||
|
*/
|
||||||
|
getForm(name = 'uniList') {
|
||||||
|
let parent = this.$parent;
|
||||||
|
let parentName = parent.$options.name;
|
||||||
|
while (parentName !== name) {
|
||||||
|
parent = parent.$parent;
|
||||||
|
if (!parent) return false
|
||||||
|
parentName = parent.$options.name;
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
},
|
||||||
|
onClick() {
|
||||||
|
if (this.to !== '') {
|
||||||
|
this.openPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.clickable || this.link) {
|
||||||
|
this.$emit('click', {
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openPage() {
|
||||||
|
if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
|
||||||
|
this.pageApi(this.link);
|
||||||
|
} else {
|
||||||
|
this.pageApi('navigateTo');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pageApi(api) {
|
||||||
|
let callback = {
|
||||||
|
url: this.to,
|
||||||
|
success: res => {
|
||||||
|
this.$emit('click', {
|
||||||
|
data: res
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: err => {
|
||||||
|
this.$emit('click', {
|
||||||
|
data: err
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (api) {
|
||||||
|
case 'navigateTo':
|
||||||
|
uni.navigateTo(callback)
|
||||||
|
break
|
||||||
|
case 'redirectTo':
|
||||||
|
uni.redirectTo(callback)
|
||||||
|
break
|
||||||
|
case 'reLaunch':
|
||||||
|
uni.reLaunch(callback)
|
||||||
|
break
|
||||||
|
case 'switchTab':
|
||||||
|
uni.switchTab(callback)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
uni.navigateTo(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" >
|
||||||
|
$uni-font-size-lg:16px;
|
||||||
|
$uni-spacing-row-sm: 5px;
|
||||||
|
$uni-spacing-row-base: 10px;
|
||||||
|
$uni-spacing-row-lg: 15px;
|
||||||
|
$background-color: #fff;
|
||||||
|
$divide-line-color: #e5e5e5;
|
||||||
|
$avatar-width: 45px;
|
||||||
|
$avatar-border-radius: 5px;
|
||||||
|
$avatar-border-color: #eee;
|
||||||
|
$avatar-border-width: 1px;
|
||||||
|
$title-size: 16px;
|
||||||
|
$title-color: #3b4144;
|
||||||
|
$title-weight: normal;
|
||||||
|
$note-size: 12px;
|
||||||
|
$note-color: #999;
|
||||||
|
$note-weight: normal;
|
||||||
|
$right-text-size: 12px;
|
||||||
|
$right-text-color: #999;
|
||||||
|
$right-text-weight: normal;
|
||||||
|
$badge-left: 0px;
|
||||||
|
$badge-top: 0px;
|
||||||
|
$dot-width: 10px;
|
||||||
|
$dot-height: 10px;
|
||||||
|
$badge-size: 18px;
|
||||||
|
$badge-font: 12px;
|
||||||
|
$badge-color: #fff;
|
||||||
|
$badge-background-color: #ff5a5f;
|
||||||
|
$badge-space: 6px;
|
||||||
|
$hover: #f5f5f5;
|
||||||
|
|
||||||
|
.uni-list-chat {
|
||||||
|
font-size: $uni-font-size-lg;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
background-color: $background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .uni-list-chat--disabled {
|
||||||
|
// opacity: 0.3;
|
||||||
|
// }
|
||||||
|
|
||||||
|
.uni-list-chat--hover {
|
||||||
|
background-color: $hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list--border {
|
||||||
|
position: relative;
|
||||||
|
margin-left: $uni-spacing-row-lg;
|
||||||
|
/* #ifdef APP-PLUS */
|
||||||
|
border-top-color: $divide-line-color;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 0.5px;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
.uni-list--border:after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
-webkit-transform: scaleY(0.5);
|
||||||
|
transform: scaleY(0.5);
|
||||||
|
background-color: $divide-line-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item--first:after {
|
||||||
|
height: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
.uni-list-chat--first {
|
||||||
|
border-top-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-ellipsis {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
lines: 1;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-ellipsis-2 {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
lines: 2;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__container {
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
flex: 1;
|
||||||
|
padding: $uni-spacing-row-base $uni-spacing-row-lg;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__header-warp {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__header {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
align-content: center;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap-reverse;
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: $avatar-width;
|
||||||
|
height: $avatar-width;
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
border-radius: $avatar-border-radius;
|
||||||
|
border-color: $avatar-border-color;
|
||||||
|
border-width: $avatar-border-width;
|
||||||
|
border-style: solid;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__header-box {
|
||||||
|
/* #ifndef APP-PLUS */
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
width: $avatar-width;
|
||||||
|
height: $avatar-width;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
/* #endif */
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__header-image {
|
||||||
|
margin: 1px;
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: $avatar-width;
|
||||||
|
height: $avatar-width;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
.uni-list-chat__header-image {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatarItem--1 {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatarItem--2 {
|
||||||
|
width: 47%;
|
||||||
|
height: 47%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatarItem--3 {
|
||||||
|
width: 32%;
|
||||||
|
height: 32%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
.header--circle {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__content {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__content-main {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-left: $uni-spacing-row-base;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__content-title {
|
||||||
|
font-size: $title-size;
|
||||||
|
color: $title-color;
|
||||||
|
font-weight: $title-weight;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.draft ,.uni-list-chat__content-note {
|
||||||
|
margin-top: 3px;
|
||||||
|
color: $note-color;
|
||||||
|
font-size: $note-size;
|
||||||
|
font-weight: $title-weight;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.draft{
|
||||||
|
color: #eb3a41;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
flex-shrink: 0;
|
||||||
|
/* #endif */
|
||||||
|
padding-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__content-extra {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-end;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__content-extra-text {
|
||||||
|
color: $right-text-color;
|
||||||
|
font-size: $right-text-size;
|
||||||
|
font-weight: $right-text-weight;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__badge-pos {
|
||||||
|
position: absolute;
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
left: 55px;
|
||||||
|
top: 3px;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
left: calc(#{$avatar-width} + 10px - #{$badge-space} + #{$badge-left});
|
||||||
|
top: calc(#{$uni-spacing-row-base}/ 2 + 1px + #{$badge-top});
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__badge {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 100px;
|
||||||
|
background-color: $badge-background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat__badge-text {
|
||||||
|
color: $badge-color;
|
||||||
|
font-size: $badge-font;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge--single {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
// left: calc(#{$avatar-width} + 7px + #{$badge-left});
|
||||||
|
/* #endif */
|
||||||
|
width: $badge-size;
|
||||||
|
height: $badge-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge--complex {
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
left: 50px;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: auto;
|
||||||
|
/* #endif */
|
||||||
|
height: $badge-size;
|
||||||
|
padding: 0 $badge-space;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-badge--dot {
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
left: 60px;
|
||||||
|
top: 6px;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
left: calc(#{$avatar-width} + 15px - #{$dot-width}/ 2 + 1px + #{$badge-left});
|
||||||
|
/* #endif */
|
||||||
|
width: $dot-width;
|
||||||
|
height: $dot-height;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-chat--right {
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
left: 0;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
542
uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
Normal file
542
uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
Normal file
@@ -0,0 +1,542 @@
|
|||||||
|
<template>
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<cell :keep-scroll-position="keepScrollPosition">
|
||||||
|
<!-- #endif -->
|
||||||
|
<view :class="{ 'uni-list-item--disabled': disabled }" :style="{'background-color':customStyle.backgroundColor}"
|
||||||
|
:hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'"
|
||||||
|
class="uni-list-item" @click="onClick">
|
||||||
|
<view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view>
|
||||||
|
<view class="uni-list-item__container"
|
||||||
|
:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column'}"
|
||||||
|
:style="{paddingTop:padding.top,paddingLeft:padding.left,paddingRight:padding.right,paddingBottom:padding.bottom}">
|
||||||
|
<slot name="header">
|
||||||
|
<view class="uni-list-item__header">
|
||||||
|
<view v-if="thumb" class="uni-list-item__icon">
|
||||||
|
<image :src="thumb" class="uni-list-item__icon-img" :class="['uni-list--' + thumbSize]" />
|
||||||
|
</view>
|
||||||
|
<view v-else-if="showExtraIcon" class="uni-list-item__icon">
|
||||||
|
<uni-icons :customPrefix="extraIcon.customPrefix" :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</slot>
|
||||||
|
<slot name="body">
|
||||||
|
<view class="uni-list-item__content"
|
||||||
|
:class="{ 'uni-list-item__content--center': thumb || showExtraIcon || showBadge || showSwitch }">
|
||||||
|
<text v-if="title" class="uni-list-item__content-title"
|
||||||
|
:class="[ellipsis !== 0 && ellipsis <= 2 ? 'uni-ellipsis-' + ellipsis : '']">{{ title }}</text>
|
||||||
|
<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
|
||||||
|
</view>
|
||||||
|
</slot>
|
||||||
|
<slot name="footer">
|
||||||
|
<view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra"
|
||||||
|
:class="{ 'flex--justify': direction === 'column' }">
|
||||||
|
<text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text>
|
||||||
|
<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" :custom-style="badgeStyle" />
|
||||||
|
<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked"
|
||||||
|
@change="onSwitchChange" />
|
||||||
|
</view>
|
||||||
|
</slot>
|
||||||
|
</view>
|
||||||
|
<uni-icons v-if="showArrow || link" :size="16" class="uni-icon-wrapper" color="#bbb" type="right" />
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
</cell>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* ListItem 列表子组件
|
||||||
|
* @description 列表子组件
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||||
|
* @property {String} title 标题
|
||||||
|
* @property {String} note 描述
|
||||||
|
* @property {String} thumb 左侧缩略图,若thumb有值,则不会显示扩展图标
|
||||||
|
* @property {String} thumbSize = [lg|base|sm] 略缩图大小
|
||||||
|
* @value lg 大图
|
||||||
|
* @value base 一般
|
||||||
|
* @value sm 小图
|
||||||
|
* @property {String} badgeText 数字角标内容
|
||||||
|
* @property {String} badgeType 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
|
||||||
|
* @property {Object} badgeStyle 数字角标样式
|
||||||
|
* @property {String} rightText 右侧文字内容
|
||||||
|
* @property {Boolean} disabled = [true|false] 是否禁用
|
||||||
|
* @property {Boolean} clickable = [true|false] 是否开启点击反馈
|
||||||
|
* @property {String} link = [navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈
|
||||||
|
* @value navigateTo 同 uni.navigateTo()
|
||||||
|
* @value redirectTo 同 uni.redirectTo()
|
||||||
|
* @value reLaunch 同 uni.reLaunch()
|
||||||
|
* @value switchTab 同 uni.switchTab()
|
||||||
|
* @property {String | PageURIString} to 跳转目标页面
|
||||||
|
* @property {Boolean} showBadge = [true|false] 是否显示数字角标
|
||||||
|
* @property {Boolean} showSwitch = [true|false] 是否显示Switch
|
||||||
|
* @property {Boolean} switchChecked = [true|false] Switch是否被选中
|
||||||
|
* @property {Boolean} showExtraIcon = [true|false] 左侧是否显示扩展图标
|
||||||
|
* @property {Object} extraIcon 扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'}
|
||||||
|
* @property {String} direction = [row|column] 排版方向
|
||||||
|
* @value row 水平排列
|
||||||
|
* @value column 垂直排列
|
||||||
|
* @event {Function} click 点击 uniListItem 触发事件
|
||||||
|
* @event {Function} switchChange 点击切换 Switch 时触发
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'UniListItem',
|
||||||
|
emits: ['click', 'switchChange'],
|
||||||
|
props: {
|
||||||
|
direction: {
|
||||||
|
type: String,
|
||||||
|
default: 'row'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
ellipsis: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
clickable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showArrow: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
to: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
showBadge: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
showSwitch: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
switchChecked: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
badgeText: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
badgeType: {
|
||||||
|
type: String,
|
||||||
|
default: 'success'
|
||||||
|
},
|
||||||
|
badgeStyle: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rightText: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
thumb: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
thumbSize: {
|
||||||
|
type: String,
|
||||||
|
default: 'base'
|
||||||
|
},
|
||||||
|
showExtraIcon: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
extraIcon: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {
|
||||||
|
type: '',
|
||||||
|
color: '#000000',
|
||||||
|
size: 20,
|
||||||
|
customPrefix: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
customStyle: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {
|
||||||
|
padding: '',
|
||||||
|
backgroundColor: '#FFFFFF'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keepScrollPosition: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'customStyle.padding': {
|
||||||
|
handler(padding) {
|
||||||
|
if(typeof padding == 'number'){
|
||||||
|
padding += ''
|
||||||
|
}
|
||||||
|
let paddingArr = padding.split(' ')
|
||||||
|
if (paddingArr.length === 1) {
|
||||||
|
const allPadding = paddingArr[0]
|
||||||
|
this.padding = {
|
||||||
|
"top": allPadding,
|
||||||
|
"right": allPadding,
|
||||||
|
"bottom": allPadding,
|
||||||
|
"left": allPadding
|
||||||
|
}
|
||||||
|
} else if (paddingArr.length === 2) {
|
||||||
|
const [verticalPadding, horizontalPadding] = paddingArr;
|
||||||
|
this.padding = {
|
||||||
|
"top": verticalPadding,
|
||||||
|
"right": horizontalPadding,
|
||||||
|
"bottom": verticalPadding,
|
||||||
|
"left": horizontalPadding
|
||||||
|
}
|
||||||
|
} else if(paddingArr.length === 3) {
|
||||||
|
const [topPadding, horizontalPadding, bottomPadding] = paddingArr;
|
||||||
|
this.padding = {
|
||||||
|
"top": topPadding,
|
||||||
|
"right": horizontalPadding,
|
||||||
|
"bottom": bottomPadding,
|
||||||
|
"left": horizontalPadding
|
||||||
|
}
|
||||||
|
} else if (paddingArr.length === 4) {
|
||||||
|
const [topPadding, rightPadding, bottomPadding, leftPadding] = paddingArr;
|
||||||
|
this.padding = {
|
||||||
|
"top": topPadding,
|
||||||
|
"right": rightPadding,
|
||||||
|
"bottom": bottomPadding,
|
||||||
|
"left": leftPadding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// inject: ['list'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isFirstChild: false,
|
||||||
|
padding: {
|
||||||
|
top: "",
|
||||||
|
right: "",
|
||||||
|
bottom: "",
|
||||||
|
left: ""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.list = this.getForm()
|
||||||
|
// 判断是否存在 uni-list 组件
|
||||||
|
if (this.list) {
|
||||||
|
if (!this.list.firstChildAppend) {
|
||||||
|
this.list.firstChildAppend = true;
|
||||||
|
this.isFirstChild = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 获取父元素实例
|
||||||
|
*/
|
||||||
|
getForm(name = 'uniList') {
|
||||||
|
let parent = this.$parent;
|
||||||
|
let parentName = parent.$options.name;
|
||||||
|
while (parentName !== name) {
|
||||||
|
parent = parent.$parent;
|
||||||
|
if (!parent) return false
|
||||||
|
parentName = parent.$options.name;
|
||||||
|
}
|
||||||
|
return parent;
|
||||||
|
},
|
||||||
|
onClick() {
|
||||||
|
if (this.to !== '') {
|
||||||
|
this.openPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.clickable || this.link) {
|
||||||
|
this.$emit('click', {
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSwitchChange(e) {
|
||||||
|
this.$emit('switchChange', e.detail);
|
||||||
|
},
|
||||||
|
openPage() {
|
||||||
|
if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
|
||||||
|
this.pageApi(this.link);
|
||||||
|
} else {
|
||||||
|
this.pageApi('navigateTo');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pageApi(api) {
|
||||||
|
let callback = {
|
||||||
|
url: this.to,
|
||||||
|
success: res => {
|
||||||
|
this.$emit('click', {
|
||||||
|
data: res
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: err => {
|
||||||
|
this.$emit('click', {
|
||||||
|
data: err
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (api) {
|
||||||
|
case 'navigateTo':
|
||||||
|
uni.navigateTo(callback)
|
||||||
|
break
|
||||||
|
case 'redirectTo':
|
||||||
|
uni.redirectTo(callback)
|
||||||
|
break
|
||||||
|
case 'reLaunch':
|
||||||
|
uni.reLaunch(callback)
|
||||||
|
break
|
||||||
|
case 'switchTab':
|
||||||
|
uni.switchTab(callback)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
uni.navigateTo(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
$uni-font-size-sm:12px;
|
||||||
|
$uni-font-size-base:14px;
|
||||||
|
$uni-font-size-lg:16px;
|
||||||
|
$uni-spacing-col-lg: 12px;
|
||||||
|
$uni-spacing-row-lg: 15px;
|
||||||
|
$uni-img-size-sm:20px;
|
||||||
|
$uni-img-size-base:26px;
|
||||||
|
$uni-img-size-lg:40px;
|
||||||
|
$uni-border-color:#e5e5e5;
|
||||||
|
$uni-bg-color-hover:#f1f1f1;
|
||||||
|
$uni-text-color-grey:#999;
|
||||||
|
$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
|
||||||
|
|
||||||
|
.uni-list-item {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
font-size: $uni-font-size-lg;
|
||||||
|
position: relative;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #fff;
|
||||||
|
flex-direction: row;
|
||||||
|
/* #ifdef H5 */
|
||||||
|
cursor: pointer;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item--disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item--hover {
|
||||||
|
background-color: $uni-bg-color-hover !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__container {
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
padding: $list-item-pd;
|
||||||
|
padding-left: $uni-spacing-row-lg;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
// align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container--right {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// .border--left {
|
||||||
|
// margin-left: $uni-spacing-row-lg;
|
||||||
|
// }
|
||||||
|
.uni-list--border {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
border-top-color: $uni-border-color;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 0.5px;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
.uni-list--border:after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 1px;
|
||||||
|
content: '';
|
||||||
|
-webkit-transform: scaleY(0.5);
|
||||||
|
transform: scaleY(0.5);
|
||||||
|
background-color: $uni-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
.uni-list-item__content {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
padding-right: 8px;
|
||||||
|
flex: 1;
|
||||||
|
color: #3b4144;
|
||||||
|
// overflow: hidden;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__content--center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__content-title {
|
||||||
|
font-size: $uni-font-size-base;
|
||||||
|
color: #3b4144;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__content-note {
|
||||||
|
margin-top: 6rpx;
|
||||||
|
color: $uni-text-color-grey;
|
||||||
|
font-size: $uni-font-size-sm;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__extra {
|
||||||
|
// width: 25%;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__header {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__icon {
|
||||||
|
margin-right: 18rpx;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__icon-img {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: block;
|
||||||
|
/* #endif */
|
||||||
|
height: $uni-img-size-base;
|
||||||
|
width: $uni-img-size-base;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-icon-wrapper {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex--direction {
|
||||||
|
flex-direction: column;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
align-items: initial;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex--justify {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
justify-content: initial;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list--lg {
|
||||||
|
height: $uni-img-size-lg;
|
||||||
|
width: $uni-img-size-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list--base {
|
||||||
|
height: $uni-img-size-base;
|
||||||
|
width: $uni-img-size-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list--sm {
|
||||||
|
height: $uni-img-size-sm;
|
||||||
|
width: $uni-img-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list-item__extra-text {
|
||||||
|
color: $uni-text-color-grey;
|
||||||
|
font-size: $uni-font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-ellipsis-1 {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
lines: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-ellipsis-2 {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
lines: 2;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
123
uni_modules/uni-list/components/uni-list/uni-list.vue
Normal file
123
uni_modules/uni-list/components/uni-list/uni-list.vue
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
<template>
|
||||||
|
<!-- #ifndef APP-NVUE -->
|
||||||
|
<view class="uni-list uni-border-top-bottom">
|
||||||
|
<view v-if="border" class="uni-list--border-top"></view>
|
||||||
|
<slot />
|
||||||
|
<view v-if="border" class="uni-list--border-bottom"></view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<list :bounce="false" :scrollable="true" show-scrollbar :render-reverse="renderReverse" @scroll="scroll" class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop"
|
||||||
|
loadmoreoffset="15">
|
||||||
|
<slot />
|
||||||
|
</list>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* List 列表
|
||||||
|
* @description 列表组件
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
|
||||||
|
* @property {String} border = [true|false] 标题
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'uniList',
|
||||||
|
'mp-weixin': {
|
||||||
|
options: {
|
||||||
|
multipleSlots: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
stackFromEnd:{
|
||||||
|
type: Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
enableBackToTop: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
scrollY: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
renderReverse:{
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// provide() {
|
||||||
|
// return {
|
||||||
|
// list: this
|
||||||
|
// };
|
||||||
|
// },
|
||||||
|
created() {
|
||||||
|
this.firstChildAppend = false;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
loadMore(e) {
|
||||||
|
this.$emit('scrolltolower');
|
||||||
|
},
|
||||||
|
scroll(e) {
|
||||||
|
this.$emit('scroll', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
$uni-bg-color:#ffffff;
|
||||||
|
$uni-border-color:#e5e5e5;
|
||||||
|
|
||||||
|
.uni-list {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
background-color: $uni-bg-color;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list--border {
|
||||||
|
position: relative;
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
border-top-color: $uni-border-color;
|
||||||
|
border-top-style: solid;
|
||||||
|
border-top-width: 0.5px;
|
||||||
|
border-bottom-color: $uni-border-color;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
border-bottom-width: 0.5px;
|
||||||
|
/* #endif */
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
|
||||||
|
.uni-list--border-top {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 1px;
|
||||||
|
-webkit-transform: scaleY(0.5);
|
||||||
|
transform: scaleY(0.5);
|
||||||
|
background-color: $uni-border-color;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-list--border-bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 1px;
|
||||||
|
-webkit-transform: scaleY(0.5);
|
||||||
|
transform: scaleY(0.5);
|
||||||
|
background-color: $uni-border-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
</style>
|
||||||
65
uni_modules/uni-list/components/uni-list/uni-refresh.vue
Normal file
65
uni_modules/uni-list/components/uni-list/uni-refresh.vue
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
|
||||||
|
<slot />
|
||||||
|
</refresh>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef APP-NVUE -->
|
||||||
|
<view ref="uni-refresh" class="uni-refresh" v-show="isShow">
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'UniRefresh',
|
||||||
|
props: {
|
||||||
|
display: {
|
||||||
|
type: [String],
|
||||||
|
default: "hide"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pulling: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isShow() {
|
||||||
|
if (this.display === "show" || this.pulling === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {},
|
||||||
|
methods: {
|
||||||
|
onchange(value) {
|
||||||
|
this.pulling = value;
|
||||||
|
},
|
||||||
|
onrefresh(e) {
|
||||||
|
this.$emit("refresh", e);
|
||||||
|
},
|
||||||
|
onpullingdown(e) {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$emit("pullingdown", e);
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
var detail = {
|
||||||
|
viewHeight: 90,
|
||||||
|
pullingDistance: e.height
|
||||||
|
}
|
||||||
|
this.$emit("pullingdown", detail);
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.uni-refresh {
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
87
uni_modules/uni-list/components/uni-list/uni-refresh.wxs
Normal file
87
uni_modules/uni-list/components/uni-list/uni-refresh.wxs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
var pullDown = {
|
||||||
|
threshold: 95,
|
||||||
|
maxHeight: 200,
|
||||||
|
callRefresh: 'onrefresh',
|
||||||
|
callPullingDown: 'onpullingdown',
|
||||||
|
refreshSelector: '.uni-refresh'
|
||||||
|
};
|
||||||
|
|
||||||
|
function ready(newValue, oldValue, ownerInstance, instance) {
|
||||||
|
var state = instance.getState()
|
||||||
|
state.canPullDown = newValue;
|
||||||
|
// console.log(newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchStart(e, instance) {
|
||||||
|
var state = instance.getState();
|
||||||
|
state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
|
||||||
|
state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
|
||||||
|
if (!state.canPullDown) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log("touchStart");
|
||||||
|
|
||||||
|
state.height = 0;
|
||||||
|
state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
|
||||||
|
state.refreshInstance.setStyle({
|
||||||
|
'height': 0
|
||||||
|
});
|
||||||
|
state.refreshInstance.callMethod("onchange", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchMove(e, ownerInstance) {
|
||||||
|
var instance = e.instance;
|
||||||
|
var state = instance.getState();
|
||||||
|
if (!state.canPullDown) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldHeight = state.height;
|
||||||
|
var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
|
||||||
|
var height = endY - state.touchStartY;
|
||||||
|
if (height > pullDown.maxHeight) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var refreshInstance = state.refreshInstance;
|
||||||
|
refreshInstance.setStyle({
|
||||||
|
'height': height + 'px'
|
||||||
|
});
|
||||||
|
|
||||||
|
height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
|
||||||
|
state.height = height;
|
||||||
|
refreshInstance.callMethod(pullDown.callPullingDown, {
|
||||||
|
height: height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function touchEnd(e, ownerInstance) {
|
||||||
|
var state = e.instance.getState();
|
||||||
|
if (!state.canPullDown) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
state.refreshInstance.callMethod("onchange", false);
|
||||||
|
|
||||||
|
var refreshInstance = state.refreshInstance;
|
||||||
|
if (state.height > pullDown.threshold) {
|
||||||
|
refreshInstance.callMethod(pullDown.callRefresh);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshInstance.setStyle({
|
||||||
|
'height': 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function propObserver(newValue, oldValue, instance) {
|
||||||
|
pullDown = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
touchmove: touchMove,
|
||||||
|
touchstart: touchStart,
|
||||||
|
touchend: touchEnd,
|
||||||
|
propObserver: propObserver
|
||||||
|
}
|
||||||
108
uni_modules/uni-list/package.json
Normal file
108
uni_modules/uni-list/package.json
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
{
|
||||||
|
"id": "uni-list",
|
||||||
|
"displayName": "uni-list 列表",
|
||||||
|
"version": "1.2.17",
|
||||||
|
"description": "List 组件 ,帮助使用者快速构建列表。",
|
||||||
|
"keywords": [
|
||||||
|
"",
|
||||||
|
"uni-ui",
|
||||||
|
"uniui",
|
||||||
|
"列表",
|
||||||
|
"",
|
||||||
|
"list"
|
||||||
|
],
|
||||||
|
"repository": "https://github.com/dcloudio/uni-ui",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "",
|
||||||
|
"uni-app": "^4.08",
|
||||||
|
"uni-app-x": ""
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"example": "../../temps/example_temps"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": ""
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||||
|
"type": "component-vue",
|
||||||
|
"darkmode": "x",
|
||||||
|
"i18n": "x",
|
||||||
|
"widescreen": "x"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [
|
||||||
|
"uni-badge",
|
||||||
|
"uni-icons"
|
||||||
|
],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "x",
|
||||||
|
"aliyun": "x",
|
||||||
|
"alipay": "x"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"uni-app": {
|
||||||
|
"vue": {
|
||||||
|
"vue2": "√",
|
||||||
|
"vue3": "√"
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"safari": "√",
|
||||||
|
"chrome": "√"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"vue": "√",
|
||||||
|
"nvue": "-",
|
||||||
|
"android": "√",
|
||||||
|
"ios": "√",
|
||||||
|
"harmony": "√"
|
||||||
|
},
|
||||||
|
"mp": {
|
||||||
|
"weixin": "√",
|
||||||
|
"alipay": "√",
|
||||||
|
"toutiao": "√",
|
||||||
|
"baidu": "√",
|
||||||
|
"kuaishou": "-",
|
||||||
|
"jd": "-",
|
||||||
|
"harmony": "-",
|
||||||
|
"qq": "√",
|
||||||
|
"lark": "-"
|
||||||
|
},
|
||||||
|
"quickapp": {
|
||||||
|
"huawei": "√",
|
||||||
|
"union": "√"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uni-app-x": {
|
||||||
|
"web": {
|
||||||
|
"safari": "-",
|
||||||
|
"chrome": "-"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"android": "-",
|
||||||
|
"ios": "-",
|
||||||
|
"harmony": "-"
|
||||||
|
},
|
||||||
|
"mp": {
|
||||||
|
"weixin": "-"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
uni_modules/uni-list/readme.md
Normal file
46
uni_modules/uni-list/readme.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
## List 列表
|
||||||
|
> **组件名:uni-list**
|
||||||
|
> 代码块: `uList`、`uListItem`
|
||||||
|
> 关联组件:`uni-list-item`、`uni-badge`、`uni-icons`、`uni-list-chat`、`uni-list-ad`
|
||||||
|
|
||||||
|
|
||||||
|
List 列表组件,包含基本列表样式、可扩展插槽机制、长列表性能优化、多端兼容。
|
||||||
|
|
||||||
|
在vue页面里,它默认使用页面级滚动。在app-nvue页面里,它默认使用原生list组件滚动。这样的长列表,在滚动出屏幕外后,系统会回收不可见区域的渲染内存资源,不会造成滚动越长手机越卡的问题。
|
||||||
|
|
||||||
|
uni-list组件是父容器,里面的核心是uni-list-item子组件,它代表列表中的一个可重复行,子组件可以无限循环。
|
||||||
|
|
||||||
|
uni-list-item有很多风格,uni-list-item组件通过内置的属性,满足一些常用的场景。当内置属性不满足需求时,可以通过扩展插槽来自定义列表内容。
|
||||||
|
|
||||||
|
内置属性可以覆盖的场景包括:导航列表、设置列表、小图标列表、通信录列表、聊天记录列表。
|
||||||
|
|
||||||
|
涉及很多大图或丰富内容的列表,比如类今日头条的新闻列表、类淘宝的电商列表,需要通过扩展插槽实现。
|
||||||
|
|
||||||
|
下文均有样例给出。
|
||||||
|
|
||||||
|
uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29)
|
||||||
|
|
||||||
|
### [点击查看详细文档](https://uniapp.dcloud.io/component/uniui/uni-indexed-list)
|
||||||
|
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 基于uni-list扩展的页面模板
|
||||||
|
|
||||||
|
通过扩展插槽,可实现多种常见样式的列表
|
||||||
|
|
||||||
|
**新闻列表类**
|
||||||
|
|
||||||
|
1. 云端一体混合布局:[https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546)
|
||||||
|
2. 云端一体垂直布局,大图模式:[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583)
|
||||||
|
3. 云端一体垂直布局,多行图文混排:[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584)
|
||||||
|
4. 云端一体垂直布局,多图模式:[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585)
|
||||||
|
5. 云端一体水平布局,左图右文:[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586)
|
||||||
|
6. 云端一体水平布局,左文右图:[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587)
|
||||||
|
7. 云端一体垂直布局,无图模式,主标题+副标题:[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588)
|
||||||
|
|
||||||
|
**商品列表类**
|
||||||
|
|
||||||
|
1. 云端一体列表/宫格视图互切:[https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651)
|
||||||
|
2. 云端一体列表(宫格模式):[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671)
|
||||||
|
3. 云端一体列表(列表模式):[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672)
|
||||||
Reference in New Issue
Block a user