This commit is contained in:
KuroSago 2024-08-28 20:39:20 +08:00
parent 6f66f1b340
commit f1d291ec72
15 changed files with 132 additions and 206 deletions

View File

@ -10,18 +10,18 @@
interface Props {
icon: string
size?: string | number
color?: string
className?: string
}
const props = withDefaults(defineProps<Props>(), {
size: 'inherit',
color: 'inherit',
class: '',
});
const iconSize = computed(() => (Number.isNaN(Number(props.size)) ? `${props.size}` : `${props.size}rpx`));
</script>
<template>
<text class="iconify-icon" :class="[props.icon]" />
<span class="iconify-icon " :class="[props.icon, props.className]" />
</template>
<style lang="scss" scoped>
@ -29,6 +29,5 @@ const iconSize = computed(() => (Number.isNaN(Number(props.size)) ? `${props.siz
display: inline-block;
line-height: 1;
font-size: v-bind('iconSize');
color: v-bind('color');
}
</style>

View File

@ -20,7 +20,7 @@
},
"meta": {
"tabBar": true,
"ignoreAuth": true
"ignoreAuth": false
}
},
{

View File

@ -4,7 +4,7 @@ import { useUserStore } from '@/stores/modules/user';
const router = useRouter();
const userStore = useUserStore();
const { loginOrNot, userInfo } = storeToRefs(userStore);
const { isLogined, userInfo } = storeToRefs(userStore);
function handleJump(url: string) {
router.push(url);
@ -18,7 +18,7 @@ function handleLoginOut() {
<template>
<view class="text-md pt-36 bg-primary">
<view v-if="loginOrNot" class="text-center">
<view v-if="isLogined" class="text-center">
<image class="w-8 h-8" :src="userInfo?.avatar" />
<view class="mt-2">
{{ userInfo?.nickname }}
@ -28,7 +28,7 @@ function handleLoginOut() {
<BasicButton @click="handleJump('/pages/log/index?id=4345&title=log&word=关键词')">
log
</BasicButton>
<BasicButton v-if="loginOrNot" @click="handleLoginOut">
<BasicButton v-if="isLogined" @click="handleLoginOut">
登出
</BasicButton>
<BasicButton v-else @click="handleJump('/pages/login/index')">

View File

@ -1,21 +1,13 @@
<script lang="ts" setup>
import Iconify from '@/components/Iconify/index.vue';
const demo = ref('Demo');
</script>
<template>
<view class="flex flex-col items-center justify-center pt-36 text-lg font-medium">
{{ demo }}
<view class="mt-30px">
iconify 组件
</view>
<view class="mt-30px center flex flex-row gap-10px">
<Iconify icon="i-mdi-account-box" size="64" color="blue" />
<Iconify icon="i-mdi-account-box" size="48" color="orange" />
<Iconify icon="i-mdi-account-box" size="32" color="green" />
<Iconify icon="i-mdi-account-box" />
<Iconify icon="i-svg-spinners-12-dots-scale-rotate" />
<view class="mt-[30px] center flex flex-row gap-10px">
<Iconify icon="i-mdi-account-box" size="66" class="text-[#987622]" />
</view>
</view>
</template>

View File

@ -1,9 +1,16 @@
<script setup lang="ts">
import { getRandomIcon } from '@/utils/character';
import { platform } from '@/utils/platform';
import { useUserStore } from '@/stores/modules/user';
const logo = getRandomIcon();
const appTitle = 'uniapp-vue3';
onMounted(async () => {
const userStore = useUserStore();
const { isLogined } = userStore;
console.log('isLogined ', isLogined);
});
</script>
<template>

View File

@ -4,6 +4,7 @@ import { useUserStore } from '@/stores/modules/user';
import { Toast } from '@/utils/uniapi/prompt';
const pageQuery = ref<Record<string, any> | undefined>(undefined);
onLoad((query) => {
pageQuery.value = query;
});
@ -16,15 +17,17 @@ const form = reactive({
});
const userStore = useUserStore();
function submit(e: any) {
userStore.login(e.detail.value).then(() => {
async function submit(e: any) {
await userStore.login(e.detail.value);
Toast('登录成功', { duration: 1500 });
console.log('pageQuery', unref(pageQuery));
setTimeout(() => {
if (unref(pageQuery)?.redirect) {
// redirect()
const params = omit(unref(pageQuery), ['redirect', 'tabBar']);
console.log('params', params);
if (unref(pageQuery)) {
// replacetabbarreplaceAll
// eslint-disable-next-line ts/no-unused-expressions
unref(pageQuery)?.tabBar === 'true'
? router.replaceAll({ name: unref(pageQuery)?.redirect, params })
@ -35,7 +38,6 @@ function submit(e: any) {
router.back();
}
}, 1500);
});
}
</script>
@ -63,48 +65,5 @@ function submit(e: any) {
</template>
<style lang="scss" scoped>
.container {
margin: 0 auto;
width: 80%;
.title {
padding: 320rpx 0 32rpx 0;
text-align: center;
}
.form-wrap {
padding: 20rpx 24rpx;
box-shadow: 16rpx 16rpx 30rpx #e5e7eb;
.form {
.form-item {
display: flex;
height: 88rpx;
border-bottom: 2rpx solid #dbeafe;
align-items: center;
.form-label {
min-width: 96rpx;
}
.form-element {
flex-grow: 1;
}
}
.submit-btn {
margin-top: 44rpx;
border: 4rpx solid #bfdbfe;
background-color: #60a5fa;
border-radius: 8rpx;
font-size: 28rpx;
color: #ffffff;
:hover {
background-color: #3b82f6;
}
}
}
}
}
</style>

View File

@ -17,17 +17,50 @@
-->
<script lang="ts" setup>
import { useUserStore } from '@/stores/modules/user';
import { useSystemInfoStore } from '@/stores/modules/system';
const { changeThemeModel } = useSystemInfoStore();
const router = useRouter();
onMounted(async () => {
const userStore = useUserStore();
const { loginOrNot } = userStore;
console.log('loginOrNot ', loginOrNot);
const { isLogined } = userStore;
console.log('isLogined ', isLogined);
userStore.initUserInfo();
//
if (isLogined) {
router.pushTab({
name: 'Home',
});
} else {
router.replace({
name: 'Login',
params: {
redirect: 'Home',
tabBar: 'true',
},
});
}
});
// fuc :
function changeTheme() {
const { themeModel } = useSystemInfoStore();
changeThemeModel({
model: themeModel === 'DARK' ? 'LIGHT' : 'DARK',
});
}
</script>
<template>
<view>
流转
<view class=" bg-primary">
<span class="text-#123">流转</span>
<button
@click="changeTheme"
>
4
</button>
</view>
</template>

View File

@ -1,4 +1,5 @@
import type { Router } from 'uni-mini-router/lib/interfaces';
import { useUserStore } from '@/stores/modules/user';
export function createRouterGuard(router: Router) {
createBeforeEachGuard(router);
@ -7,15 +8,15 @@ export function createRouterGuard(router: Router) {
function createBeforeEachGuard(router: Router) {
router.beforeEach((to, _, next) => {
const _isLogin = true;
const { isLogined } = useUserStore();
if (to && to?.meta?.ignoreAuth) {
// 如果目标路由忽略验证直接跳转
next();
} else if (!_isLogin && to && to.name !== 'Login') {
} else if (!isLogined && to && to.name !== 'Login') {
// 如果没有登录且目标路由不是登录页面则跳转到登录页面
// 将目标路由和参数传入登录页面,登录成功后直接跳转到目标路由,优化体验
next({ name: 'Login', params: { redirect: to.name!, ...to.query }, navType: 'push' });
} else if (_isLogin && to && to.name === 'Login') {
} else if (isLogined && to && to.name === 'Login') {
// 如果已经登录且目标页面是登录页面则跳转至首页
next({ name: 'Home', navType: 'replaceAll' });
} else {
@ -27,13 +28,13 @@ function createBeforeEachGuard(router: Router) {
function createAfterEachGuard(router: Router) {
router.afterEach((to) => {
const { isLogined } = useUserStore();
if (to && to?.meta?.ignoreAuth)
return;
const _isLogin = true;
if (!_isLogin && to && to.name !== 'Login') {
if (!isLogined && to && to.name !== 'Login') {
// 如果没有登录且目标路由不是登录页面则跳转到登录页面
router.push({ name: 'Login', params: { ...to.query } });
} else if (_isLogin && to && to.name === 'Login') {
} else if (isLogined && to && to.name === 'Login') {
// 如果已经登录且目标页面是登录页面则跳转至首页
router.replaceAll({ name: 'Home' });
}

View File

@ -12,6 +12,7 @@ const router = createRouter({
export function setupRouter(app: App<Element>) {
// Configure router guard
console.log('app ===', app);
createRouterGuard(router);
app.use(router);
}

View File

@ -2,9 +2,10 @@ import { THEME_MODEL } from '@/enums/UI';
import type { ThemeCfg } from '@/model/theme';
import { theme as _theme } from '@/theme/theme';
type ThemeModelKey = keyof typeof THEME_MODEL;
interface SystemInfo {
theme: ThemeCfg
themeModel: THEME_MODEL
themeModel: ThemeModelKey
systemInfo: UniApp.GetSystemInfoResult
}
@ -12,11 +13,10 @@ export const useSystemInfoStore = defineStore({
id: 'system',
state: (): SystemInfo => ({
// 主题
// theme: <ThemeCfg>Object.assign(_theme.light),
theme: <ThemeCfg>{ ..._theme.light },
// 当前主题模式
themeModel: THEME_MODEL.LIGHT as THEME_MODEL,
themeModel: 'LIGHT',
// 系统信息
systemInfo: {
@ -32,9 +32,9 @@ export const useSystemInfoStore = defineStore({
},
// 切换主题
changeThemeModel({ model = THEME_MODEL.DARK as THEME_MODEL }) {
changeThemeModel({ model }: { model: ThemeModelKey } = { model: 'DARK' }) {
this.themeModel = model;
this.theme = { ..._theme[model] };
this.theme = { ..._theme[THEME_MODEL[model]] };
},
},
persist: {

View File

@ -15,7 +15,7 @@ export const useUserStore = defineStore({
userInfo: null,
}),
getters: {
loginOrNot: state => !!state.token,
isLogined: state => !!state.token,
},
actions: {
@ -26,15 +26,15 @@ export const useUserStore = defineStore({
// 登录
async login(params: LoginParams) {
const { send: sendLogin } = useRequest(loginApi, { immediate: false });
try {
const res = await sendLogin(params);
this.token = res.token;
this.setToken(res.token);
await this.getUserInfo();
} catch (error) {
throw error;
}
this.setToken('res.token');
// const { send: sendLogin } = useRequest(loginApi, { immediate: false });
// try {
// const res = await sendLogin(params);
// this.setToken(res.token);
// await this.getUserInfo();
// } catch (error) {
// throw error;
// }
},
// 获取用户信息

View File

@ -7,10 +7,6 @@
* key
* key , bug
*/
// container {
// // ThemeColor
// '--source': '#00bdd4',
// }
/**
* secondary
@ -19,7 +15,12 @@
* neutral
*/
export const theme = {
import type { THEME_MODEL } from '@/enums/UI';
import type { ThemeCfg } from '@/model/theme';
export const theme: {
[key in THEME_MODEL]: ThemeCfg
} = {
light: {
/* light */
@ -94,7 +95,7 @@ export const theme = {
/* dark */
/* 颜色 */
'--colors-primary': '#FFE274',
'--colors-primary': '#123',
'--colors-secondary': '#5A7767', // 次要
'--colors-accent': '#FB9300', // 强调
@ -185,7 +186,6 @@ export function buildTheme() {
const extendList = [ExtendStyle.OPACITY];
flattenedObj.forEach((_v: string, k: string) => {
// const [_, key, value] = k.match(/^--(.+?)-(.+)$/) || [0, 'key', 'value'];
const [_, key, value] = k.match(/^--([^-]+)-(.+)$/) || [0, 'key', 'value'];
if (extendList.includes(key as ExtendStyle)) {

View File

@ -1,18 +0,0 @@
import { getIconCollections, iconsPlugin } from '@egoist/tailwindcss-icons';
import { isMp } from './build/platform';
/** @type {import('tailwindcss').Config} */
export default {
content: ['./public/index.html', './src/**/*.{html,js,ts,jsx,tsx,vue}'],
theme: {
extend: {},
},
corePlugins: {
// 小程序去使用 h5 的 preflight 和响应式 container 没有意义
preflight: !isMp,
container: !isMp,
},
plugins: [iconsPlugin({
collections: getIconCollections(['mdi', 'svg-spinners']),
})],
};

View File

@ -1,41 +1,17 @@
/**
* unocss defineConfig
* @link unocss: https://github.com/unocss/unocss
* @link unocss-preset-weapp: https://github.com/MellowCo/unocss-preset-weapp
*/
import presetWeapp from 'unocss-preset-weapp';
import { extractorAttributify, transformerClass } from 'unocss-preset-weapp/transformer';
import { presetIcons } from 'unocss';
import transformerDirectives from '@unocss/transformer-directives';
const { presetWeappAttributify, transformerAttributify } = extractorAttributify();
import { getIconCollections, iconsPlugin } from '@egoist/tailwindcss-icons';
import { isMp } from './build/platform';
/** @type {import('tailwindcss').Config} */
export default {
presets: [
// https://github.com/MellowCo/unocss-preset-weapp
presetWeapp(),
// attributify autocomplete
presetWeappAttributify(),
presetIcons(),
],
shortcuts: [
{
'border-base': 'border border-gray-500_10',
'center': 'flex justify-center items-center',
content: ['./public/index.html', './src/**/**.{html,js,ts,jsx,tsx,vue}'],
corePlugins: {
// 小程序去使用 h5 的 preflight 和响应式 container 没有意义
preflight: !isMp,
container: !isMp,
},
],
transformers: [
transformerDirectives({
enforce: 'pre',
}),
// https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerAttributify
transformerAttributify(),
// https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerClass
transformerClass(),
],
plugins: [iconsPlugin({
collections: getIconCollections(['mdi', 'svg-spinners']),
})],
theme: {
extend: {
opacity: {

View File

@ -2,9 +2,10 @@ import * as fs from 'node:fs';
import { buildTheme } from '../../src/theme/theme';
export default function buildThemeConfig() {
const fileName = './tailwind.config.ts';
const _data = buildTheme();
// 写入时会先清空文件
fs.writeFile('./unocss.config.ts', `${createFileByTemplate(_data)}`, (err: any) => {
fs.writeFile(fileName, `${createFileByTemplate(_data)}`, (err: any) => {
if (err) {
console.error(err);
} else {
@ -36,47 +37,22 @@ function flatten(obj: any, parentKey = ''): any {
// 通过模版生成文件
function createFileByTemplate(theme: any) {
const fileString = `
/**
* unocss defineConfig
* @link unocss: https://github.com/unocss/unocss
* @link unocss-preset-weapp: https://github.com/MellowCo/unocss-preset-weapp
* */
import presetWeapp from 'unocss-preset-weapp'
import { extractorAttributify, transformerClass } from 'unocss-preset-weapp/transformer'
import { presetIcons } from 'unocss'
import transformerDirectives from '@unocss/transformer-directives'
const { presetWeappAttributify, transformerAttributify } = extractorAttributify()
import { getIconCollections, iconsPlugin } from '@egoist/tailwindcss-icons';
import { isMp } from './build/platform';
/** @type {import('tailwindcss').Config} */
export default {
presets: [
// https://github.com/MellowCo/unocss-preset-weapp
presetWeapp(),
// attributify autocomplete
presetWeappAttributify(),
presetIcons(),
],
shortcuts: [
{
'border-base': 'border border-gray-500_10',
'center': 'flex justify-center items-center',
content: ['./public/index.html', './src/**/**.{html,js,ts,jsx,tsx,vue}'],
corePlugins: {
// 小程序去使用 h5 的 preflight 和响应式 container 没有意义
preflight: !isMp,
container: !isMp,
},
],
transformers: [
transformerDirectives({
enforce: 'pre',
}),
// https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerAttributify
transformerAttributify(),
// https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerClass
transformerClass(),
],
theme: ${JSON.stringify(theme, null, 2)}
}
plugins: [iconsPlugin({
collections: getIconCollections(['mdi', 'svg-spinners']),
})],
theme: ${JSON.stringify(theme, null, 4)}
};
`;
return fileString;
}