init_base
This commit is contained in:
parent
a5ddee13a6
commit
bc6002f70c
1
.env.example
Normal file
1
.env.example
Normal file
@ -0,0 +1 @@
|
||||
VITE_APP_API=
|
||||
15
.eslintrc.cjs
Normal file
15
.eslintrc.cjs
Normal file
@ -0,0 +1,15 @@
|
||||
/* eslint-env node */
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
'extends': [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/eslint-config-typescript',
|
||||
'@vue/eslint-config-prettier/skip-formatting'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest'
|
||||
}
|
||||
}
|
||||
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
|
||||
# Env
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Vscode
|
||||
.vscode
|
||||
8
.prettierrc.json
Normal file
8
.prettierrc.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"tabWidth": 4,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
30
README.md
30
README.md
@ -1 +1,31 @@
|
||||
# web-wallet
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
yarn
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
yarn dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
yarn build-only
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Format code
|
||||
|
||||
```sh
|
||||
yarn format
|
||||
```
|
||||
|
||||
14
index.html
Normal file
14
index.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" href="/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Web Wallet</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
43
package.json
Normal file
43
package.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "webtoon-admin",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p type-check \"build-only {@}\" --",
|
||||
"preview": "vite preview",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --build --force",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"axios": "^1.6.8",
|
||||
"dayjs": "^1.11.10",
|
||||
"pinia": "^2.1.7",
|
||||
"vue": "^3.4.21",
|
||||
"vue-router": "^4.3.0",
|
||||
"vue3-i18n": "^1.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.8.0",
|
||||
"@tsconfig/node20": "^20.1.4",
|
||||
"@types/node": "^20.12.5",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"@vue/eslint-config-typescript": "^13.0.0",
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-vue": "^9.23.0",
|
||||
"npm-run-all2": "^6.1.2",
|
||||
"prettier": "^3.2.5",
|
||||
"sass": "^1.75.0",
|
||||
"typescript": "~5.4.0",
|
||||
"vite": "^5.2.8",
|
||||
"vite-plugin-vue-devtools": "^7.0.25",
|
||||
"vue-tsc": "^2.0.11"
|
||||
}
|
||||
}
|
||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
20
src/App.vue
Normal file
20
src/App.vue
Normal file
@ -0,0 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { LayoutVue } from '@/components/common'
|
||||
|
||||
const config = {
|
||||
token: {
|
||||
colorPrimary: '#ff7789',
|
||||
borderRadius: 0,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-config-provider :theme="config" :autoInsertSpaceInButton="false">
|
||||
<LayoutVue>
|
||||
<router-view />
|
||||
</LayoutVue>
|
||||
</a-config-provider>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
50
src/api/config/index.ts
Normal file
50
src/api/config/index.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import axios from 'axios'
|
||||
import router from '@/router'
|
||||
import { STATUS_CODE_SUCCESS, ACCESS_TOKEN, STATUS_CODE_UNAUTHORIZED } from '@/helpers'
|
||||
|
||||
axios.defaults.withCredentials = false
|
||||
|
||||
export const API_URL = import.meta.env.VITE_APP_API
|
||||
const instance = axios.create({
|
||||
baseURL: API_URL,
|
||||
})
|
||||
|
||||
instance.interceptors.request.use(
|
||||
function (config: any) {
|
||||
try {
|
||||
const token = localStorage.getItem(ACCESS_TOKEN)
|
||||
if (token) {
|
||||
config.headers['Authorization'] = `Bearer ${token}`
|
||||
}
|
||||
} catch (error) {
|
||||
throw Error('')
|
||||
}
|
||||
return config
|
||||
},
|
||||
function (error) {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
instance.interceptors.response.use(
|
||||
function (response) {
|
||||
if (response?.status !== STATUS_CODE_SUCCESS) return Promise.reject(response?.data)
|
||||
return response.data
|
||||
},
|
||||
function (error) {
|
||||
if (error?.response?.status === STATUS_CODE_UNAUTHORIZED || error.code === 'ERR_NETWORK') {
|
||||
localStorage.clear()
|
||||
return router.push({ name: 'login' })
|
||||
}
|
||||
if (error?.response?.data) {
|
||||
return Promise.reject(error?.response?.data)
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export const setLocaleApi = (locale: string) => {
|
||||
instance.defaults.headers.common['lang'] = locale
|
||||
}
|
||||
|
||||
export default instance
|
||||
290
src/assets/scss/__base.scss
Normal file
290
src/assets/scss/__base.scss
Normal file
@ -0,0 +1,290 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100;200;300;400;500;600;700;800;900&display=swap');
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Noto Sans JP';
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--vt-c-gray-2);
|
||||
background: var(--color-background);
|
||||
transition:
|
||||
color 0.5s,
|
||||
background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family: 'Noto Sans JP';
|
||||
font-size: 15px;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
* {
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--vt-c-main-gray-v1);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: var(--vt-c-main-gray-v2);
|
||||
border-radius: 10px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
position: unset;
|
||||
}
|
||||
|
||||
.box {
|
||||
// padding: 20px;
|
||||
&.full {
|
||||
min-height: calc(100% - 20px);
|
||||
}
|
||||
&.no-border {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.box-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 66px;
|
||||
padding: 0 20px;
|
||||
background-color: var(--vt-c-white-mute);
|
||||
|
||||
.box-search {
|
||||
display: flex;
|
||||
gap: 35px;
|
||||
align-items: center;
|
||||
|
||||
.ant-input-search {
|
||||
width: 322px;
|
||||
|
||||
.ant-input {
|
||||
border: none;
|
||||
background: unset;
|
||||
outline: unset;
|
||||
box-shadow: unset;
|
||||
}
|
||||
|
||||
.ant-input-group-addon {
|
||||
background: unset;
|
||||
.ant-input-search-button {
|
||||
background: unset;
|
||||
border: unset;
|
||||
box-shadow: unset;
|
||||
.anticon {
|
||||
svg {
|
||||
fill: var(--vt-c-gray-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 900;
|
||||
font-size: 18px;
|
||||
line-height: 26px;
|
||||
color: var(--vt-c-gray-2);
|
||||
.title-page {
|
||||
color: var(--vt-c-gray-v9);
|
||||
}
|
||||
|
||||
&.manga {
|
||||
color: var(--vt-c-gray-v9);
|
||||
}
|
||||
}
|
||||
|
||||
.box-btn {
|
||||
@include center_flex;
|
||||
width: 140px;
|
||||
height: 40px;
|
||||
border-radius: 6px;
|
||||
color: var(--vt-c-main);
|
||||
background-color: var(--vt-c-white);
|
||||
box-shadow: var(--vt-box-shadow);
|
||||
border: 1px solid var(--vt-c-main);
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.box-body {
|
||||
padding: 0 20px;
|
||||
overflow-y: auto;
|
||||
height: calc(100vh - 135px);
|
||||
position: relative;
|
||||
|
||||
&.no-pagination {
|
||||
height: calc(100vh - 66px);
|
||||
}
|
||||
|
||||
&:has(.form-create-chap) {
|
||||
.ant-tabs {
|
||||
overflow-y: auto;
|
||||
height: calc(100vh - 235px);
|
||||
}
|
||||
}
|
||||
|
||||
&.no_padding {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.btn-save-setting {
|
||||
&:disabled {
|
||||
border-color: var(--vt-c-gray-1);
|
||||
background-color: var(--vt-c-gray-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-base {
|
||||
margin-right: 12px;
|
||||
|
||||
&.btn-delete {
|
||||
background-color: var(--vt-c-red-v3);
|
||||
color: var(--vt-c-white);
|
||||
|
||||
&:hover {
|
||||
border-color: unset !important;
|
||||
color: var(--vt-c-white);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-tag {
|
||||
&.custom {
|
||||
width: 72px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
@include center_flex;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-picker {
|
||||
width: 100%;
|
||||
&.has-value {
|
||||
border-color: var(--vt-c-main);
|
||||
}
|
||||
}
|
||||
|
||||
.rounded-btn {
|
||||
border-radius: 100px !important;
|
||||
}
|
||||
.bold-label {
|
||||
label {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-input-number {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ant-input[disabled] {
|
||||
background-color: var(--vt-c-background-dark-1);
|
||||
color: var(--vt-c-text-dark-3);
|
||||
}
|
||||
|
||||
.ant-tabs {
|
||||
&.custom {
|
||||
.ant-tabs-nav {
|
||||
background-color: var(--vt-c-white-mute);
|
||||
padding: 0 20px;
|
||||
}
|
||||
.ant-tabs-content-holder {
|
||||
padding: 0 20px;
|
||||
}
|
||||
.ant-tabs-nav-list {
|
||||
.ant-tabs-tab {
|
||||
min-width: 68px;
|
||||
justify-content: center;
|
||||
padding: 0 16px 6px;
|
||||
.ant-tabs-tab-btn {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
line-height: 23.17px;
|
||||
}
|
||||
|
||||
&:not(.ant-tabs-tab-active) {
|
||||
color: var(--vt-c-gray-v9);
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-tabs-ink-bar {
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
.ant-tabs-content {
|
||||
&:has(.tab-report) {
|
||||
height: calc(100vh - 180px);
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
&:has(.tab-ranking) {
|
||||
height: calc(100vh - 180px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.manga-tabs {
|
||||
.ant-tabs-content-holder {
|
||||
margin-bottom: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
&.master-tabs {
|
||||
.ant-tabs-content-holder {
|
||||
margin-bottom: 70px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-form-item {
|
||||
.ant-form-item-explain-error {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-spin-spinning {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
@include center_flex;
|
||||
}
|
||||
|
||||
.flex-col-center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
170
src/assets/scss/__mixin.scss
Normal file
170
src/assets/scss/__mixin.scss
Normal file
@ -0,0 +1,170 @@
|
||||
@mixin screen($size) {
|
||||
$desktop: '(min-width: 1281px)';
|
||||
$tablet: '(min-width: 768px) and (max-width: 1280px)';
|
||||
$mobile: '(max-width: 767px)';
|
||||
|
||||
@if $size == desktop {
|
||||
@media only screen and #{$desktop} {
|
||||
@content;
|
||||
}
|
||||
} @else if $size == tablet {
|
||||
@media only screen and #{$tablet} {
|
||||
@content;
|
||||
}
|
||||
} @else if $size == mobile {
|
||||
@media only screen and #{$mobile} {
|
||||
@content;
|
||||
}
|
||||
} @else {
|
||||
@media only screen and #{$size} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin text-shorten($numLines: 1) {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
@supports (-webkit-line-clamp: $numLines) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: initial;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: $numLines;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
|
||||
$start: 0;
|
||||
$end: 30;
|
||||
|
||||
@for $i from $start through $end {
|
||||
.pl-#{$i} {
|
||||
padding-left: #{$i}px;
|
||||
}
|
||||
.pr-#{$i} {
|
||||
padding-right: #{$i}px;
|
||||
}
|
||||
.pb-#{$i} {
|
||||
padding-bottom: #{$i}px;
|
||||
}
|
||||
.pt-#{$i} {
|
||||
padding-top: #{$i}px;
|
||||
}
|
||||
.ml-#{$i} {
|
||||
margin-left: #{$i}px;
|
||||
}
|
||||
.mr-#{$i} {
|
||||
margin-right: #{$i}px;
|
||||
}
|
||||
.mb-#{$i} {
|
||||
margin-bottom: #{$i}px;
|
||||
}
|
||||
.mt-#{$i} {
|
||||
margin-top: #{$i}px;
|
||||
}
|
||||
.mx-#{$i} {
|
||||
margin: 0 #{$i}px;
|
||||
}
|
||||
.fz-#{$i} {
|
||||
font-size: #{$i}px;
|
||||
}
|
||||
.px-#{$i} {
|
||||
padding: 0 #{$i}px;
|
||||
}
|
||||
.py-#{$i} {
|
||||
padding: #{$i}px 0;
|
||||
}
|
||||
.text-shorten-#{$i} {
|
||||
@include text-shorten(#{$i});
|
||||
}
|
||||
}
|
||||
$maxFontWeight: 1000;
|
||||
|
||||
$positions: top, left, right, bottom, none;
|
||||
|
||||
@each $position in $positions {
|
||||
@if $position == none {
|
||||
.bh-#{$position} {
|
||||
border-style: none !important;
|
||||
}
|
||||
} @else {
|
||||
.bh-#{$position} {
|
||||
border-#{$position}-style: hidden !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$positionsText: start, end, right, left, center;
|
||||
@each $pt in $positionsText {
|
||||
.text-#{$pt} {
|
||||
text-align: #{$pt};
|
||||
}
|
||||
}
|
||||
|
||||
$fw: 100;
|
||||
@while $fw < $maxFontWeight {
|
||||
.fw-#{$fw} {
|
||||
font-weight: $fw;
|
||||
}
|
||||
$fw: $fw + 100;
|
||||
}
|
||||
|
||||
@mixin center_flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@mixin center_pos {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@mixin line_clamp($line) {
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: $line;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
@mixin position($pos: absolute, $left: 0, $right: 0, $top: 0, $bottom: 0) {
|
||||
position: $pos;
|
||||
top: $top;
|
||||
left: $left;
|
||||
right: $right;
|
||||
bottom: $bottom;
|
||||
}
|
||||
|
||||
// function
|
||||
@function sum($numbers...) {
|
||||
$sum: 0;
|
||||
@each $number in $numbers {
|
||||
$sum: $sum + $number;
|
||||
}
|
||||
@return $sum;
|
||||
}
|
||||
|
||||
@function calc_v2($size) {
|
||||
@return calc(100% - $size);
|
||||
}
|
||||
|
||||
@mixin baseBtn(
|
||||
$bg: var(--vt-c-main),
|
||||
$width: 92px,
|
||||
$height: 36px,
|
||||
$borderRadius: var(--vt-br-btn)
|
||||
) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: $width;
|
||||
height: $height;
|
||||
background-color: $bg;
|
||||
border-radius: $borderRadius;
|
||||
box-shadow: unset;
|
||||
}
|
||||
107
src/assets/scss/__variables.scss
Normal file
107
src/assets/scss/__variables.scss
Normal file
@ -0,0 +1,107 @@
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
--vt-c-white-v2: #d9d9d9;
|
||||
--vt-c-white-v5: #fafafa;
|
||||
--vt-c-white-v7: #f0f5f8;
|
||||
--vt-c-white-v8: #fbfbfb;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-v1: #5d6679;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
--vt-c-black-bold: #000000;
|
||||
--vt-c-black-bold-v2: #131523;
|
||||
--vt-c-black-bold-v3: #252c32;
|
||||
--vt-c-black-bold-v3: #00000026;
|
||||
--vt-c-black-bold-v4: #00000080;
|
||||
--vt-c-black-bold-v5: #00000008;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
--vt-c-text-dark-3: rgba(0, 0, 0, 0.88);
|
||||
|
||||
--vt-c-background-dark-1: rgba(0, 0, 0, 0.04);
|
||||
|
||||
--vt-box-shadow-1: 0px 0px 8px rgba(78, 37, 0, 0.78);
|
||||
--vt-box-shadow-2: 0px 4px 4px rgba(0, 0, 0, 0.25);
|
||||
--vt-box-shadow-3: 0px 0px 5px 0px var(--vt-c-black-bold-v5) inset;
|
||||
|
||||
--vt-c-main: #ff7789;
|
||||
--vt-c-main-title: #519fb0;
|
||||
--vt-c-main-light: #6659ff;
|
||||
--vt-c-main-bg: #eff1f7;
|
||||
--vt-c-main-bg-v1: #f4f7ff;
|
||||
--vt-c-main-black: #051121;
|
||||
--vt-c-main-clear: #e6e8ef;
|
||||
--vt-c-main-link: #4335ef;
|
||||
--vt-c-main-red: red;
|
||||
--vt-c-main-gray: #7e84a3;
|
||||
--vt-c-main-gray-v1: #fff3;
|
||||
--vt-c-main-gray-v2: #0003;
|
||||
--vt-c-gray-v4: #a9a5a3;
|
||||
--vt-c-gray-v5: #666666;
|
||||
--vt-c-gray-v6: #999999;
|
||||
--vt-c-gray-v9: #888888;
|
||||
--vt-c-gray-v10: #444444;
|
||||
--vt-c-gray-v11: #6d6d6d;
|
||||
--vt-c-gray-v12: #b9bdc7;
|
||||
--vt-c-gray-v17: #e6e6e6;
|
||||
--vt-c-blue: #3375f3;
|
||||
--vt-c-blue-v3: #162dff;
|
||||
--vt-c-blue-v4: #67abba;
|
||||
--vt-c-blue-v5: #20aee5;
|
||||
--vt-c-red-v3: #ff0f0f;
|
||||
|
||||
--vt-c-violet: #5671fb;
|
||||
--vt-c-pink: #ffe6ea;
|
||||
--vt-c-pink-2: #ff6d6d;
|
||||
--vt-c-pink-3: #e05266;
|
||||
--vt-c-green: #1e8e3e;
|
||||
--vt-c-green-2: #93cb9c;
|
||||
--vt-c-green-3: #429d7c;
|
||||
|
||||
--vt-c-turquoise: #3fb3ce;
|
||||
|
||||
--color-background: #f5f7fb;
|
||||
--color-background-event: #3fb3ce;
|
||||
--color-background-sidebar: #e6e6e6;
|
||||
--color-background-soft: var(--vt-c-white-soft);
|
||||
|
||||
--color-border: #b8b7b7;
|
||||
--color-border-v1: #cdd4e7;
|
||||
--color-border-shadow: #dfdfdf40;
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--font-size: 14px;
|
||||
--vt-font-btn: 92px;
|
||||
--vt-br-btn: 3px;
|
||||
--section-gap: 160px;
|
||||
|
||||
--vt-c-gray-1: #e9e9e9;
|
||||
--vt-c-gray-2: #444444;
|
||||
--vt-c-gray-3: #adadad66;
|
||||
--vt-c-gray-4: #f9f9f9;
|
||||
--vt-c-gray-5: #b4b4b4;
|
||||
--vt-c-gray-6: #d9d9d9;
|
||||
--vt-c-gray-7: #ececec;
|
||||
--vt-c-gray-8: #636363;
|
||||
--vt-c-gray-9: #aaaaaa;
|
||||
--vt-c-green-dark: #435855;
|
||||
|
||||
--vt-c-orange: #f3a964;
|
||||
|
||||
--vt-box-shadow: 0px 0px 4px 0px var(--vt-c-gray-3);
|
||||
--vt-box-shadow-active: 0px 0px 4px 0px var(--vt-c-main);
|
||||
}
|
||||
3
src/assets/scss/main.scss
Normal file
3
src/assets/scss/main.scss
Normal file
@ -0,0 +1,3 @@
|
||||
@import '__variables';
|
||||
@import '__mixin';
|
||||
@import '__base';
|
||||
12
src/components/common/LayoutVue.vue
Normal file
12
src/components/common/LayoutVue.vue
Normal file
@ -0,0 +1,12 @@
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<template>
|
||||
<a-layout>
|
||||
<a-layout class="ant-layout-body">
|
||||
<!-- <AppHeaderVue /> -->
|
||||
<a-layout-content>
|
||||
<slot />
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
</a-layout>
|
||||
</template>
|
||||
3
src/components/common/index.ts
Normal file
3
src/components/common/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import LayoutVue from './LayoutVue.vue'
|
||||
|
||||
export { LayoutVue }
|
||||
8
src/helpers/constants/code.ts
Normal file
8
src/helpers/constants/code.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export const STATUS_CODE_SUCCESS = 200
|
||||
export const STATUS_CODE_BAD_REQUEST = 400
|
||||
export const STATUS_CODE_UNAUTHORIZED = 401
|
||||
export const STATUS_CODE_FORBIDDEN = 403
|
||||
export const STATUS_CODE_NOT_FOUND = 404
|
||||
export const STATUS_CODE_VALIDATE_ERROR = 422
|
||||
export const STATUS_CODE_SERVER_ERROR = 500
|
||||
export const HTTP_TOO_MANY_REQUESTS = 429
|
||||
16
src/helpers/constants/constants.ts
Normal file
16
src/helpers/constants/constants.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
export const PAGE_FIRST = 1
|
||||
export const PER_PAGE = 40
|
||||
export const MAX_STRING = 255
|
||||
|
||||
export const CURRENT_DAY = dayjs(new Date()).format('DD')
|
||||
export const CURRENT_MONTH = dayjs(new Date()).format('MM')
|
||||
export const CURRENT_YEAR = dayjs(new Date()).format('YYYY')
|
||||
export const MONTHS = Array.from({ length: 12 }, (item, i) => {
|
||||
return dayjs(new Date(0, i)).format('MM')
|
||||
})
|
||||
|
||||
export const FORMAT_DAY = (day: any, format = 'YYYY-MM-DD') => {
|
||||
return dayjs(new Date(day)).format(format)
|
||||
}
|
||||
7
src/helpers/constants/localStorage.ts
Normal file
7
src/helpers/constants/localStorage.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export const ACCESS_TOKEN = 'access_token'
|
||||
|
||||
export const USER = 'user'
|
||||
|
||||
export const getToken = () => localStorage.getItem(ACCESS_TOKEN)
|
||||
|
||||
export const getAdmin = () => localStorage.getItem(USER)
|
||||
3
src/helpers/index.ts
Normal file
3
src/helpers/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './constants/code'
|
||||
export * from './constants/constants'
|
||||
export * from './constants/localStorage'
|
||||
12
src/lang/en/base.ts
Normal file
12
src/lang/en/base.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export default {
|
||||
logout: 'Logout',
|
||||
login: 'Login',
|
||||
mail_address: 'Email',
|
||||
password: 'Password',
|
||||
create: 'Create',
|
||||
edit: 'Edit',
|
||||
update: 'Update',
|
||||
detail: 'Detail',
|
||||
submit: 'Submit',
|
||||
cancel: 'Cancel',
|
||||
}
|
||||
7
src/lang/en/index.ts
Normal file
7
src/lang/en/index.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import validation from './validation'
|
||||
import base from './base'
|
||||
|
||||
export const en = {
|
||||
...base,
|
||||
validation,
|
||||
}
|
||||
150
src/lang/en/validation.ts
Normal file
150
src/lang/en/validation.ts
Normal file
@ -0,0 +1,150 @@
|
||||
export default {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines contain the default error messages used by
|
||||
| the validator class. Some of these rules have multiple versions such
|
||||
| as the size rules. Feel free to tweak each of these messages here.
|
||||
|
|
||||
*/
|
||||
|
||||
accepted: 'The {0} must be accepted.',
|
||||
accepted_if: 'The {0} must be accepted when {1} is {2}.',
|
||||
active_url: 'The {0} is not a valid URL.',
|
||||
after: 'The {0} must be a date after {1}.',
|
||||
after_or_equal: 'The {0} must be a date after or equal to {1}.',
|
||||
alpha: 'The {0} must only contain letters.',
|
||||
alpha_dash: 'The {0} must only contain letters, numbers, dashes and underscores.',
|
||||
alpha_num: 'The {0} must only contain letters and numbers.',
|
||||
array: 'The {0} must be an array.',
|
||||
ascii: 'The {0} must only contain single-byte alphanumeric characters and symbols.',
|
||||
before: 'The {0} must be a date before {1}.',
|
||||
before_or_equal: 'The {0} must be a date before or equal to {1}.',
|
||||
between: {
|
||||
array: 'The {0} must have between {1} and {2} items.',
|
||||
file: 'The {0} must be between {1} and {2} kilobytes.',
|
||||
numeric: 'The {0} must be between {1} and {2}.',
|
||||
string: 'The {0} must be between {1} and {2} characters.',
|
||||
},
|
||||
boolean: 'The {0} field must be true or false.',
|
||||
confirmed: 'The {0} confirmation does not match.',
|
||||
current_password: 'The password is incorrect.',
|
||||
date: 'The {0} is not a valid date.',
|
||||
date_equals: 'The {0} must be a date equal to {1}.',
|
||||
date_format: 'The {0} does not match the format {1}.',
|
||||
decimal: 'The {0} must have {1} decimal places.',
|
||||
declined: 'The {0} must be declined.',
|
||||
declined_if: 'The {0} must be declined when {1} is {2}.',
|
||||
different: 'The {0} and {1} must be different.',
|
||||
digits: 'The {0} must be {1} digits.',
|
||||
digits_between: 'The {0} must be between {1} and {2} digits.',
|
||||
dimensions: 'The {0} has invalid image dimensions.',
|
||||
distinct: 'The {0} field has a duplicate value.',
|
||||
doesnt_end_with: 'The {0} may not end with one of the following: {1}.',
|
||||
doesnt_start_with: 'The {0} may not start with one of the following: {1}.',
|
||||
email: 'The {0} must be a valid email address.',
|
||||
ends_with: 'The {0} must end with one of the following: {1}.',
|
||||
enum: 'The selected {0} is invalid.',
|
||||
exists: 'The selected {0} is invalid.',
|
||||
file: 'The {0} must be a file.',
|
||||
filled: 'The {0} field must have a value.',
|
||||
gt: {
|
||||
array: 'The {0} must have more than {1} items.',
|
||||
file: 'The {0} must be greater than {1} kilobytes.',
|
||||
numeric: 'The {0} must be greater than {1}.',
|
||||
string: 'The {0} must be greater than {1} characters.',
|
||||
},
|
||||
gte: {
|
||||
array: 'The {0} must have {1} items or more.',
|
||||
file: 'The {0} must be greater than or equal to {1} kilobytes.',
|
||||
numeric: 'The {0} must be greater than or equal to {1}.',
|
||||
string: 'The {0} must be greater than or equal to {1} characters.',
|
||||
},
|
||||
image: 'The {0} must be an image.',
|
||||
in: 'The selected {0} is invalid.',
|
||||
in_array: 'The {0} field does not exist in {1}.',
|
||||
integer: 'The {0} must be an integer.',
|
||||
ip: 'The {0} must be a valid IP address.',
|
||||
ipv4: 'The {0} must be a valid IPv4 address.',
|
||||
ipv6: 'The {0} must be a valid IPv6 address.',
|
||||
json: 'The {0} must be a valid JSON string.',
|
||||
lowercase: 'The {0} must be lowercase.',
|
||||
lt: {
|
||||
array: 'The {0} must have less than {1} items.',
|
||||
file: 'The {0} must be less than {1} kilobytes.',
|
||||
numeric: 'The {0} must be less than {1}.',
|
||||
string: 'The {0} must be less than {1} characters.',
|
||||
},
|
||||
lte: {
|
||||
array: 'The {0} must not have more than {1} items.',
|
||||
file: 'The {0} must be less than or equal to {1} kilobytes.',
|
||||
numeric: 'The {0} must be less than or equal to {1}.',
|
||||
string: 'The {0} must be less than or equal to {1} characters.',
|
||||
},
|
||||
mac_address: 'The {0} must be a valid MAC address.',
|
||||
max: {
|
||||
array: 'The {0} must not have more than {1} items.',
|
||||
file: 'The {0} must not be greater than {1} kilobytes.',
|
||||
numeric: 'The {0} must not be greater than {1}.',
|
||||
string: 'The {0} must not be greater than {1} characters.',
|
||||
},
|
||||
max_digits: 'The {0} must not have more than {1} digits.',
|
||||
mimes: 'The {0} must be a file of type: {1}s.',
|
||||
mimetypes: 'The {0} must be a file of type: {1}s.',
|
||||
min: {
|
||||
array: 'The {0} must have at least {1} items.',
|
||||
file: 'The {0} must be at least {1} kilobytes.',
|
||||
numeric: 'The {0} must be at least {1}.',
|
||||
string: 'The {0} must be at least {1} characters.',
|
||||
},
|
||||
min_digits: 'The {0} must have at least {1} digits.',
|
||||
missing: 'The {0} field must be missing.',
|
||||
missing_if: 'The {0} field must be missing when {1} is {2}.',
|
||||
missing_unless: 'The {0} field must be missing unless {1} is {2}.',
|
||||
missing_with: 'The {0} field must be missing when {1}s is present.',
|
||||
missing_with_all: 'The {0} field must be missing when {1}s are present.',
|
||||
multiple_of: 'The {0} must be a multiple of {1}.',
|
||||
not_in: 'The selected {0} is invalid.',
|
||||
not_regex: 'The {0} format is invalid.',
|
||||
numeric: 'The {0} must be a number.',
|
||||
password: {
|
||||
letters: 'The {0} must contain at least one letter.',
|
||||
mixed: 'The {0} must contain at least one uppercase and one lowercase letter.',
|
||||
numbers: 'The {0} must contain at least one number.',
|
||||
symbols: 'The {0} must contain at least one symbol.',
|
||||
uncompromised: 'The given {0} has appeared in a data leak. Please choose a different {1}.',
|
||||
},
|
||||
present: 'The {0} field must be present.',
|
||||
prohibited: 'The {0} field is prohibited.',
|
||||
prohibited_if: 'The {0} field is prohibited when {1} is {2}.',
|
||||
prohibited_unless: 'The {0} field is prohibited unless {1} is in {2}s.',
|
||||
prohibits: 'The {0} field prohibits {1} from being present.',
|
||||
regex: 'The {0} format is invalid.',
|
||||
required: 'The {0} field is required.',
|
||||
required_array_keys: 'The {0} field must contain entries for: {1}s.',
|
||||
required_if: 'The {0} field is required when {1} is {2}.',
|
||||
required_if_accepted: 'The {0} field is required when {1} is accepted.',
|
||||
required_unless: 'The {0} field is required unless {1} is in {2}s.',
|
||||
required_with: 'The {0} field is required when {1}s is present.',
|
||||
required_with_all: 'The {0} field is required when {1}s are present.',
|
||||
required_without: 'The {0} field is required when {1}s is not present.',
|
||||
required_without_all: 'The {0} field is required when none of {1}s are present.',
|
||||
same: 'The {0} and {1} must match.',
|
||||
size: {
|
||||
array: 'The {0} must contain {1} items.',
|
||||
file: 'The {0} must be {1} kilobytes.',
|
||||
numeric: 'The {0} must be {1}.',
|
||||
string: 'The {0} must be {1} characters.',
|
||||
},
|
||||
starts_with: 'The {0} must start with one of the following: {1}s.',
|
||||
string: 'The {0} must be a string.',
|
||||
timezone: 'The {0} must be a valid timezone.',
|
||||
unique: 'The {0} has already been taken.',
|
||||
uploaded: 'The {0} failed to upload.',
|
||||
uppercase: 'The {0} must be uppercase.',
|
||||
url: 'The {0} must be a valid URL.',
|
||||
ulid: 'The {0} must be a valid ULID.',
|
||||
uuid: 'The {0} must be a valid UUID.',
|
||||
}
|
||||
16
src/lang/index.ts
Normal file
16
src/lang/index.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { createI18n } from 'vue3-i18n'
|
||||
import { en } from './en'
|
||||
import { jp } from './jp'
|
||||
|
||||
const messages = {
|
||||
en: en,
|
||||
jp: jp,
|
||||
}
|
||||
|
||||
const i18n = createI18n({
|
||||
locale: 'jp',
|
||||
fallbackLocale: 'jp',
|
||||
messages,
|
||||
} as any)
|
||||
|
||||
export default i18n
|
||||
1
src/lang/jp/base.ts
Normal file
1
src/lang/jp/base.ts
Normal file
@ -0,0 +1 @@
|
||||
export default {}
|
||||
9
src/lang/jp/index.ts
Normal file
9
src/lang/jp/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import base from './base'
|
||||
import validation from './validation'
|
||||
import notFound from './notFound'
|
||||
|
||||
export const jp = {
|
||||
...base,
|
||||
validation,
|
||||
notFound,
|
||||
}
|
||||
4
src/lang/jp/notFound.ts
Normal file
4
src/lang/jp/notFound.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export default {
|
||||
title: 'ご指定のページはございませんでした。',
|
||||
back: ' トップページへ',
|
||||
}
|
||||
115
src/lang/jp/validation.ts
Normal file
115
src/lang/jp/validation.ts
Normal file
@ -0,0 +1,115 @@
|
||||
export default {
|
||||
active_url: '{0}は有効なURLではありません',
|
||||
after: '{0}は{1}より後の日付にしてください',
|
||||
after_or_equal: '{0}は{1}以降の日付にしてください',
|
||||
alpha: '{0}は英字のみ有効です',
|
||||
alpha_dash: '{0}は「英字」「数字」「-(ダッシュ)」「_(下線)」のみ有効です',
|
||||
alpha_num: '{0}は「英字」「数字」のみ有効です',
|
||||
array: '{0}は配列タイプのみ有効です',
|
||||
before: '{0}は{1}より前の日付にしてください',
|
||||
before_or_equal: '{0}は{1}以前の日付にしてください',
|
||||
between: {
|
||||
numeric: '{0}は {1} ~ {2} までの数値まで有効です',
|
||||
file: '{0}は {1} ~ {2} キロバイトまで有効です',
|
||||
string: '{0}は {1} ~ {2} 文字まで有効です',
|
||||
array: '{0}は {1} ~ {2} 個まで有効です',
|
||||
},
|
||||
boolean: '{0}の値は true もしくは false のみ有効です',
|
||||
confirmed: '{0}を確認用と一致させてください',
|
||||
date: '{0}を有効な日付形式にしてください',
|
||||
date_format: '{0}を{1}書式と一致させてください',
|
||||
different: '{0}を{1}と違うものにしてください',
|
||||
digits: '{0}は:digits桁のみ有効です',
|
||||
digits_between: '{0}は{1} ~ {2}桁のみ有効です',
|
||||
dimensions: '{0}ルールに合致する画像サイズのみ有効です',
|
||||
distinct: '{0}に重複している値があります',
|
||||
email: '{0}の書式のみ有効です',
|
||||
exists: '{0}無効な値です',
|
||||
file: '{0}アップロード出来ないファイルです',
|
||||
filled: '{0}値を入力してください',
|
||||
gt: {
|
||||
numeric: '{0}は{1}より大きい必要があります。',
|
||||
file: '{0}は{1}キロバイトより大きい必要があります。',
|
||||
string: '{0}は{1}文字より多い必要があります。',
|
||||
array: '{0}には{1} 個より多くの項目が必要です。',
|
||||
},
|
||||
gte: {
|
||||
numeric: '{0}は{1}以上である必要があります。',
|
||||
file: '{0}は{1}キロバイト以上である必要があります。',
|
||||
string: '{0}は{1}文字以上である必要があります。',
|
||||
array: '{0}には{1}個以上の項目が必要です。',
|
||||
},
|
||||
image: {
|
||||
type: '画像は「jpg」「png」「jpeg」のみ有効です',
|
||||
max: '{0}は{1}MB以下のファイルのみ有効です',
|
||||
},
|
||||
in: '{0}無効な値です',
|
||||
in_array: '{0}は{1}と一致する必要があります',
|
||||
integer: '{0}は整数のみ有効です',
|
||||
ip: '{0}IPアドレスの書式のみ有効です',
|
||||
ipv4: '{0}IPアドレス(IPv4)の書式のみ有効です',
|
||||
ipv6: '{0}IPアドレス(IPv6)の書式のみ有効です',
|
||||
json: '{0}正しいJSON文字列のみ有効です',
|
||||
lt: {
|
||||
numeric: '{0}は{1}未満である必要があります。',
|
||||
file: '{0}は{1}キロバイト未満である必要があります。',
|
||||
string: '{0}は{1}文字未満である必要があります。',
|
||||
array: '{0}は{1}未満の項目を持つ必要があります。',
|
||||
},
|
||||
lte: {
|
||||
numeric: '{0}は{1}以下である必要があります。',
|
||||
file: '{0}は{1}キロバイト以下である必要があります。',
|
||||
string: '{0}は{1}文字以下である必要があります。',
|
||||
array: '{0}は{1}以上の項目を持つ必要があります。',
|
||||
},
|
||||
max: {
|
||||
numeric: '{0}は{1}以下のみ有効です',
|
||||
file: '{0}は{1}KB以下のファイルのみ有効です',
|
||||
string: '{0}は{1}文字以下のみ有効です',
|
||||
array: '{0}は{1}個以下のみ有効です',
|
||||
tags: 'ジャンルは1作品{0}個までです。',
|
||||
},
|
||||
mimes: '{0}は {1}s タイプのみ有効です',
|
||||
mimetypes: '{0}は {1}s タイプのみ有効です',
|
||||
min: {
|
||||
numeric: '{0}は{1}以上のみ有効です',
|
||||
file: '{0}は{1}KB以上のファイルのみ有効です',
|
||||
string: '{0}は{1}文字以上のみ有効です',
|
||||
array: '{0}は{1}個以上のみ有効です',
|
||||
},
|
||||
not_in: '{0}無効な値です',
|
||||
not_regex: 'The {0} format is invalid.',
|
||||
numeric: '{0}は数字のみ有効です',
|
||||
present: '{0} が存在しません',
|
||||
regex: '{0} 無効な値です',
|
||||
required: '{0}は必須です',
|
||||
required_if: '{0}は{1}が{1}には必須です',
|
||||
required_unless: '{0}は{1}が{1}sでなければ必須です',
|
||||
required_with: '{0}は{1}sが入力されている場合は必須です',
|
||||
required_with_all: '{0}は{1}sが入力されている場合は必須です',
|
||||
required_without: '{0}は{1}sが入力されていない場合は必須です',
|
||||
required_without_all: '{0}は{1}sが入力されていない場合は必須です',
|
||||
same: '{0}は{1}と同じ場合のみ有効です',
|
||||
size: {
|
||||
numeric: '{0}は{1}のみ有効です',
|
||||
file: '{0}は{1}KBのみ有効です',
|
||||
string: '{0}は{1}文字のみ有効です',
|
||||
array: '{0}は{1}個のみ有効です',
|
||||
},
|
||||
string: '{0}は文字列のみ有効です',
|
||||
timezone: '{0}正しいタイムゾーンのみ有効です',
|
||||
unique: '{0}は既に存在します',
|
||||
already_exist: '{0}は既に登録されています',
|
||||
uploaded: '{0}アップロードに失敗しました',
|
||||
url: '{0}は正しいURL書式のみ有効です',
|
||||
tel_format: '電話番号は英数字とハイフンのみ入力してください。',
|
||||
point_length: 'ポイントは {0} 文字までしか入力できません',
|
||||
point_value: '入力データの制限を超えました',
|
||||
password: {
|
||||
format: 'パスワードは半角英数字記号8文字以上入力してください。',
|
||||
confirm: 'パスワードとパスワード(再確認)が一致しません。',
|
||||
format_with_label: '{0}は半角英数字記号8文字以上入力してください。',
|
||||
},
|
||||
check_one: '少なくとも 1 つのアクティビティ タイプを選択してください',
|
||||
date_future: '{0}には、今日より前の日付を指定してください',
|
||||
}
|
||||
24
src/main.ts
Normal file
24
src/main.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import i18n from '@/lang'
|
||||
import App from './App.vue'
|
||||
import Antd from 'ant-design-vue'
|
||||
import router from './router'
|
||||
import 'ant-design-vue/dist/reset.css'
|
||||
import './assets/scss/main.scss'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(i18n)
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
app.use(Antd)
|
||||
|
||||
// Hide 'DOMNodeInserted'
|
||||
const originalAddEventListener = Element.prototype.addEventListener
|
||||
Element.prototype.addEventListener = function (type: any, listener: any, options: any) {
|
||||
if (type === 'DOMNodeInserted') return // Ignore this event type
|
||||
return originalAddEventListener.call(this, type, listener, options)
|
||||
}
|
||||
|
||||
app.mount('#app')
|
||||
13
src/router/index.ts
Normal file
13
src/router/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { routes } from './route'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
next()
|
||||
})
|
||||
|
||||
export default router
|
||||
37
src/router/route.ts
Normal file
37
src/router/route.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import * as Page from '@/views'
|
||||
import { getToken } from '@/helpers'
|
||||
|
||||
const ifAuthenticated = (to: any, from: any, next: any) => {
|
||||
if (getToken()) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
next('/login')
|
||||
}
|
||||
|
||||
const ifNotAuthenticated = (to: any, from: any, next: any) => {
|
||||
if (!getToken()) {
|
||||
next()
|
||||
return
|
||||
}
|
||||
next('/')
|
||||
}
|
||||
|
||||
export const routes: any = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/home',
|
||||
children: [
|
||||
{
|
||||
path: 'home',
|
||||
name: 'home',
|
||||
component: Page.Home,
|
||||
},
|
||||
{
|
||||
path: ':pathMatch(.*)*',
|
||||
component: Page.NotFound,
|
||||
name: 'page-not-found',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
1
src/stores/index.ts
Normal file
1
src/stores/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export {}
|
||||
7
src/views/Home/HomeView.vue
Normal file
7
src/views/Home/HomeView.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div class="box">Home page</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
73
src/views/NotFound/NotFoundView.vue
Normal file
73
src/views/NotFound/NotFoundView.vue
Normal file
@ -0,0 +1,73 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue3-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="page_404">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-10 col-sm-offset-1 text-center">
|
||||
<div class="four_zero_four_bg">
|
||||
<h1 class="text-center">404</h1>
|
||||
</div>
|
||||
<div class="contain_box_404">
|
||||
<h3 class="h2">
|
||||
{{ t('notFound.title') }}
|
||||
</h3>
|
||||
<a href="/reservations" class="link_404">
|
||||
{{ t('notFound.back') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup></script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page_404 {
|
||||
padding: 40px 0;
|
||||
background: var(--vt-c-white);
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page_404 img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.four_zero_four_bg {
|
||||
background-repeat: no-repeat;
|
||||
height: 400px;
|
||||
background-position: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.four_zero_four_bg h1 {
|
||||
font-size: 80px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.four_zero_four_bg h3 {
|
||||
font-size: 80px;
|
||||
}
|
||||
|
||||
.link_404 {
|
||||
color: var(--vt-c-white);
|
||||
padding: 10px 20px;
|
||||
background: var(--vt-c-main);
|
||||
margin: 20px 0;
|
||||
display: inline-block;
|
||||
}
|
||||
.contain_box_404 {
|
||||
margin-top: -50px;
|
||||
}
|
||||
</style>
|
||||
2
src/views/index.ts
Normal file
2
src/views/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export const Home = () => import('@/views/Home/HomeView.vue')
|
||||
export const NotFound = () => import('@/views/NotFound/NotFoundView.vue')
|
||||
14
tsconfig.app.json
Normal file
14
tsconfig.app.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||
"exclude": ["src/**/__tests__/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
13
tsconfig.node.json
Normal file
13
tsconfig.node.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "@tsconfig/node20/tsconfig.json",
|
||||
"include": ["vite.config.*", "vitest.config.*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"noEmit": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
||||
24
vite.config.ts
Normal file
24
vite.config.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import VueDevTools from 'vite-plugin-vue-devtools'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
server: {
|
||||
port: 3008,
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
VueDevTools(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
}
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user