diff --git a/index.html b/index.html index a5e4796..6143dde 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,34 @@ - - - - + + + + 营养与健康数据管理处理平台 - - -
- - + + + +
+
+
+ + + +
初始化中...
+
+
+
+ + + diff --git a/package.json b/package.json index 5816078..8bcdec5 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,11 @@ "preview": "vite preview" }, "dependencies": { - "@handsontable/vue3": "^14.0.0", + "dayjs": "^1.11.10", + "pinia": "^2.1.7", "view-ui-plus": "^1.3.15", - "vue": "^3.4.0" + "vue": "^3.4.0", + "vue-router": "4" }, "devDependencies": { "@types/node": "^20.10.5", diff --git a/src/App.vue b/src/App.vue index 1f722fd..26b676a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,69 +1,32 @@ @@ -74,6 +37,12 @@ const onMenuSelect = (name: string) => { box-sizing: border-box; } +.hideLoading { + background: rgba(255, 255, 255, 0); + pointer-events: none; + opacity: 0; +} + .app-header { display: flex; align-items: center; @@ -114,5 +83,5 @@ body { will-change: filter; transition: filter 300ms; } - +./service/api/user.ts diff --git a/src/components/data-fields/index.vue b/src/components/data-fields/index.vue index b8f95e9..790ac71 100644 --- a/src/components/data-fields/index.vue +++ b/src/components/data-fields/index.vue @@ -77,9 +77,12 @@ const onInputPaste = (e: ClipboardEvent, pIndex: number, fIndex: number) => { //border-bottom: solid 1px #eee; &:hover { - .item:not(.item-header) { - background: #fafafa; - } + // .item:not(.item-header) { + // background: #fafafa; + // } + } + &:focus-within{ + background-color: #fcf2e0; } } @@ -112,9 +115,12 @@ const onInputPaste = (e: ClipboardEvent, pIndex: number, fIndex: number) => { //transform: translateX(-1px) translateY(-1px); &:focus { - box-shadow: 0 0 5px rgba(87, 116, 189, 0.5) inset; + // box-shadow: 0 0 5px rgba(87, 116, 189, 0.5) inset; //box-shadow: 0 0 1px rgb(0, 0, 0) inset; - //outline: solid 1px rgb(87, 116, 189); + outline: solid 2px rgb(87, 116, 189); + position: relative; + left:0px; + background-color: #fff; //border-color: #ccc; //background: rgba(87,87,189,0.15); } diff --git a/src/components/login/index.vue b/src/components/login/index.vue index 0ce83e7..17126e3 100644 --- a/src/components/login/index.vue +++ b/src/components/login/index.vue @@ -1,22 +1,13 @@ + + + + diff --git a/src/core/errors.ts b/src/core/errors.ts new file mode 100644 index 0000000..ec783e7 --- /dev/null +++ b/src/core/errors.ts @@ -0,0 +1,8 @@ +export class BizError extends Error { + code: number; + + constructor(code: number, message: string='') { + super(message); + this.code = code; + } +} diff --git a/src/core/sleep.ts b/src/core/sleep.ts new file mode 100644 index 0000000..93b2081 --- /dev/null +++ b/src/core/sleep.ts @@ -0,0 +1,5 @@ +export function sleep(time: number) { + return new Promise((resolve) => { + setTimeout(resolve, time); + }) +} diff --git a/src/main.ts b/src/main.ts index eff85ba..cdafc3e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,11 @@ import { createApp } from 'vue' -// import ViewUIPlus from 'view-ui-plus' import 'view-ui-plus/dist/styles/viewuiplus.css' -import './style.css' +import { createPinia } from 'pinia' import App from './App.vue' +import router from './router' +import './style.css' createApp(App) - // .use(ViewUIPlus) + .use(createPinia()) + .use(router) .mount('#app') diff --git a/src/pages/Layout.vue b/src/pages/Layout.vue new file mode 100644 index 0000000..ef97949 --- /dev/null +++ b/src/pages/Layout.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/pages/datas.vue b/src/pages/datas.vue new file mode 100644 index 0000000..b77a46c --- /dev/null +++ b/src/pages/datas.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/src/pages/result.vue b/src/pages/result.vue new file mode 100644 index 0000000..1e86ff5 --- /dev/null +++ b/src/pages/result.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/src/pages/user.vue b/src/pages/user.vue new file mode 100644 index 0000000..d6c0588 --- /dev/null +++ b/src/pages/user.vue @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/src/router.ts b/src/router.ts new file mode 100644 index 0000000..0ad75c4 --- /dev/null +++ b/src/router.ts @@ -0,0 +1,69 @@ +import {onMounted, onUnmounted, ref} from "vue"; +import {createRouter, createWebHashHistory, RouteRecordRaw} from "vue-router"; + +function getHash() { + const hash = window.location.hash + return hash.length > 0 ? hash.slice(1) : ''; +} + +export const useHash = () => { + const hash = ref(getHash()) + + const onHashChange = () => { + hash.value = getHash() + } + onMounted(() => { + window.addEventListener('hashchange', onHashChange, false) + }) + onUnmounted(() => { + window.removeEventListener('hashchange', onHashChange, false) + }) + return hash +} + +export const routes:RouteRecordRaw[] = [ + { + path: '', + name: 'home', + meta: { + title: '输出计算' + }, + component: () => import('./pages/result.vue') + }, + { + path: 'data', + name: 'data', + meta: { + title: '数据管理' + }, + component: () => import('./pages/datas.vue') + }, + { + path: 'user', + name: 'user', + component: () => import('./pages/user.vue'), + meta: { + role: 'root', + title: '用户管理' + } + } +] + +export const router = createRouter({ + routes: [ + // 路由配置 + { + path: '/', + component: () => import('./pages/Layout.vue'), + children: routes + }, + // { + // path: '/login', + // name: 'login', + // component: () => import('./pages/login.vue') + // } + ], + history: createWebHashHistory() +}) + +export default router diff --git a/src/service/api/user.ts b/src/service/api/user.ts new file mode 100644 index 0000000..e9adac3 --- /dev/null +++ b/src/service/api/user.ts @@ -0,0 +1,29 @@ +import {BizError} from "../../core/errors.ts"; + +export type LoginModel = { + account: string; + password: string; +} + +const fakeUser: UserInfo = { + account: "admin", + nickname: "管理员", + password: "", + role: 'root', + uid: 1 +} + +export async function LoginService(params: LoginModel) { + if (params.account == 'admin' && params.password == 'admin') { + const loginInfo = Date.now().toString(16); + return { + userinfo: fakeUser, + token: loginInfo + }; + } + throw new BizError(1001, '用户名或密码错误'); +} + +export async function GetLoginInfo() { + return fakeUser; +} diff --git a/src/service/router.ts b/src/service/router.ts deleted file mode 100644 index 8ad3b21..0000000 --- a/src/service/router.ts +++ /dev/null @@ -1,22 +0,0 @@ -import {onMounted, onUnmounted, ref} from "vue"; - -function getHash() { - const hash = window.location.hash - return hash.length > 0 ? hash.slice(1) : ''; -} - -export const useHash = () => { - const hash = ref(getHash()) - - const onHashChange = () => { - hash.value = getHash() - } - onMounted(() => { - window.addEventListener('hashchange', onHashChange, false) - }) - onUnmounted(() => { - window.removeEventListener('hashchange', onHashChange, false) - }) - return hash -} - diff --git a/src/service/user-store.ts b/src/service/user-store.ts new file mode 100644 index 0000000..838c4b3 --- /dev/null +++ b/src/service/user-store.ts @@ -0,0 +1,63 @@ +import {defineStore} from "pinia" +import {onMounted, ref} from "vue" +import {GetLoginInfo, LoginService} from "./api/user"; +import {BizError} from "../core/errors.ts"; +import router from "../router.ts"; +import {sleep} from "../core/sleep.ts"; + +type LoginParam = { + account: string; + password: string; +} + +export const LOGIN_SESSION_KEY = 'x-yy-js-data-user'; + +export const useUserStore = defineStore('counter', () => { + const userInfo = ref() + const userInit = ref(false) + + // 登录 + const login = async (data: LoginParam) => { + await sleep(1000); + const info = await LoginService(data); + userInfo.value = info.userinfo; + localStorage.setItem(LOGIN_SESSION_KEY, info.token) + } + + // 登出 + const logout = async () => { + localStorage.removeItem(LOGIN_SESSION_KEY) + userInfo.value = undefined; + } + // 更新用户信息 + const updateUserInfo = async (info: UserInfo) => { + userInfo.value = info + } + // 获取用户信息 + const getUserInfo = async () => { + const token = localStorage.getItem(LOGIN_SESSION_KEY); + if (!token) { + throw new BizError(401) + } + userInfo.value = await GetLoginInfo(); + } + onMounted(() => { + getUserInfo().catch((e: BizError) => { + if (e.code == 401) { + router.replace(`/login?redirect=${router.currentRoute.value.path}`).then(() => console.log('401 show login')) + } + }).finally(() => { + console.log('onMounted inited') + userInit.value = true + }) + }) + + return { + userInfo, + userInit, + login, + logout, + updateUserInfo, + getUserInfo + } +}) diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 11f02fe..cefc0fa 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1 +1,16 @@ /// + +type int = number; +type double = number; +type bool = boolean; +type AccountRole = 'root' | 'admin' | 'user'; +type UserInfo = { + uid: number; + nickname: string; + account: string; + password: string; + avatar?: string; + lastUpdate?:string; + createTime?: string; + role: AccountRole; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b5014df..31e530b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -117,11 +117,6 @@ resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== -"@handsontable/vue3@^14.0.0": - version "14.0.0" - resolved "https://registry.npmmirror.com/@handsontable/vue3/-/vue3-14.0.0.tgz#7c62091cc3393cb556771d9678cced4622095f1c" - integrity sha512-4/XuCxXw+8d3fHB3/v0zbb9PYgyjJfU6Tol+dsxRHk0L8FGUFCM8WIDFn3DCb5PHtE2peQBIUl/HvnsCpPpEMg== - "@jridgewell/sourcemap-codec@^1.4.15": version "1.4.15" resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" @@ -203,6 +198,11 @@ "@vue/compiler-dom" "3.4.0" "@vue/shared" "3.4.0" +"@vue/devtools-api@^6.5.0": + version "6.5.1" + resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.1.tgz#7f71f31e40973eeee65b9a64382b13593fdbd697" + integrity sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA== + "@vue/language-core@1.8.27": version "1.8.27" resolved "https://registry.npmmirror.com/@vue/language-core/-/language-core-1.8.27.tgz" @@ -332,6 +332,11 @@ dayjs@^1.11.0: resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz" integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== +dayjs@^1.11.10: + version "1.11.10" + resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0" + integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ== + de-indent@^1.0.2: version "1.0.2" resolved "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz" @@ -511,6 +516,14 @@ picomatch@^2.0.4, picomatch@^2.2.1: resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pinia@^2.1.7: + version "2.1.7" + resolved "https://registry.npmmirror.com/pinia/-/pinia-2.1.7.tgz#4cf5420d9324ca00b7b4984d3fbf693222115bbc" + integrity sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ== + dependencies: + "@vue/devtools-api" "^6.5.0" + vue-demi ">=0.14.5" + popper.js@^1.14.6: version "1.16.1" resolved "https://registry.npmmirror.com/popper.js/-/popper.js-1.16.1.tgz" @@ -622,6 +635,18 @@ vite@^4.3.2: optionalDependencies: fsevents "~2.3.2" +vue-demi@>=0.14.5: + version "0.14.6" + resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.6.tgz#dc706582851dc1cdc17a0054f4fec2eb6df74c92" + integrity sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w== + +vue-router@4: + version "4.2.5" + resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.2.5.tgz#b9e3e08f1bd9ea363fdd173032620bc50cf0e98a" + integrity sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw== + dependencies: + "@vue/devtools-api" "^6.5.0" + vue-template-compiler@^2.7.14: version "2.7.16" resolved "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz"