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

View File

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

View File

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

View File

@ -1,21 +1,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import Iconify from '@/components/Iconify/index.vue';
const demo = ref('Demo');
</script> </script>
<template> <template>
<view class="flex flex-col items-center justify-center pt-36 text-lg font-medium"> <view class="flex flex-col items-center justify-center pt-36 text-lg font-medium">
{{ demo }}
<view class="mt-30px"> <view class="mt-30px">
iconify 组件 iconify 组件
</view> </view>
<view class="mt-30px center flex flex-row gap-10px"> <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="66" class="text-[#987622]" />
<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> </view>
</view> </view>
</template> </template>

View File

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

View File

@ -4,6 +4,7 @@ import { useUserStore } from '@/stores/modules/user';
import { Toast } from '@/utils/uniapi/prompt'; import { Toast } from '@/utils/uniapi/prompt';
const pageQuery = ref<Record<string, any> | undefined>(undefined); const pageQuery = ref<Record<string, any> | undefined>(undefined);
onLoad((query) => { onLoad((query) => {
pageQuery.value = query; pageQuery.value = query;
}); });
@ -16,26 +17,27 @@ const form = reactive({
}); });
const userStore = useUserStore(); const userStore = useUserStore();
function submit(e: any) { async function submit(e: any) {
userStore.login(e.detail.value).then(() => { await userStore.login(e.detail.value);
Toast('登录成功', { duration: 1500 }); Toast('登录成功', { duration: 1500 });
setTimeout(() => { console.log('pageQuery', unref(pageQuery));
if (unref(pageQuery)?.redirect) { setTimeout(() => {
// redirect() if (unref(pageQuery)?.redirect) {
const params = omit(unref(pageQuery), ['redirect', 'tabBar']); // redirect()
if (unref(pageQuery)) { const params = omit(unref(pageQuery), ['redirect', 'tabBar']);
// replacetabbarreplaceAll console.log('params', params);
// eslint-disable-next-line ts/no-unused-expressions
unref(pageQuery)?.tabBar === 'true' if (unref(pageQuery)) {
? router.replaceAll({ name: unref(pageQuery)?.redirect, params }) // eslint-disable-next-line ts/no-unused-expressions
: router.replace({ name: unref(pageQuery)?.redirect, params }); unref(pageQuery)?.tabBar === 'true'
} ? router.replaceAll({ name: unref(pageQuery)?.redirect, params })
} else { : router.replace({ name: unref(pageQuery)?.redirect, params });
//
router.back();
} }
}, 1500); } else {
}); //
router.back();
}
}, 1500);
} }
</script> </script>
@ -63,48 +65,5 @@ function submit(e: any) {
</template> </template>
<style lang="scss" scoped> <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> </style>

View File

@ -17,17 +17,50 @@
--> -->
<script lang="ts" setup> <script lang="ts" setup>
import { useUserStore } from '@/stores/modules/user'; import { useUserStore } from '@/stores/modules/user';
import { useSystemInfoStore } from '@/stores/modules/system';
const { changeThemeModel } = useSystemInfoStore();
const router = useRouter();
onMounted(async () => { onMounted(async () => {
const userStore = useUserStore(); const userStore = useUserStore();
const { loginOrNot } = userStore; const { isLogined } = userStore;
console.log('loginOrNot ', loginOrNot); console.log('isLogined ', isLogined);
userStore.initUserInfo(); 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> </script>
<template> <template>
<view> <view class=" bg-primary">
流转 <span class="text-#123">流转</span>
<button
@click="changeTheme"
>
4
</button>
</view> </view>
</template> </template>

View File

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

View File

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

View File

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

View File

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

View File

@ -7,10 +7,6 @@
* key * key
* key , bug * key , bug
*/ */
// container {
// // ThemeColor
// '--source': '#00bdd4',
// }
/** /**
* secondary * secondary
@ -19,7 +15,12 @@
* neutral * 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: {
/* light */ /* light */
@ -94,7 +95,7 @@ export const theme = {
/* dark */ /* dark */
/* 颜色 */ /* 颜色 */
'--colors-primary': '#FFE274', '--colors-primary': '#123',
'--colors-secondary': '#5A7767', // 次要 '--colors-secondary': '#5A7767', // 次要
'--colors-accent': '#FB9300', // 强调 '--colors-accent': '#FB9300', // 强调
@ -185,7 +186,6 @@ export function buildTheme() {
const extendList = [ExtendStyle.OPACITY]; const extendList = [ExtendStyle.OPACITY];
flattenedObj.forEach((_v: string, k: string) => { flattenedObj.forEach((_v: string, k: string) => {
// const [_, key, value] = k.match(/^--(.+?)-(.+)$/) || [0, 'key', 'value'];
const [_, key, value] = k.match(/^--([^-]+)-(.+)$/) || [0, 'key', 'value']; const [_, key, value] = k.match(/^--([^-]+)-(.+)$/) || [0, 'key', 'value'];
if (extendList.includes(key as ExtendStyle)) { 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 @@
/** import { getIconCollections, iconsPlugin } from '@egoist/tailwindcss-icons';
* unocss defineConfig import { isMp } from './build/platform';
* @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();
/** @type {import('tailwindcss').Config} */
export default { export default {
presets: [ content: ['./public/index.html', './src/**/**.{html,js,ts,jsx,tsx,vue}'],
// https://github.com/MellowCo/unocss-preset-weapp corePlugins: {
presetWeapp(), // 小程序去使用 h5 的 preflight 和响应式 container 没有意义
// attributify autocomplete preflight: !isMp,
presetWeappAttributify(), container: !isMp,
presetIcons(), },
], plugins: [iconsPlugin({
shortcuts: [ collections: getIconCollections(['mdi', 'svg-spinners']),
{ })],
'border-base': 'border border-gray-500_10',
'center': 'flex justify-center items-center',
},
],
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: { theme: {
extend: { extend: {
opacity: { opacity: {

View File

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