提交格式验证修改
This commit is contained in:
@@ -37,7 +37,6 @@
|
|||||||
"fmt": "oxfmt",
|
"fmt": "oxfmt",
|
||||||
"gen-route": "sa gen-route",
|
"gen-route": "sa gen-route",
|
||||||
"lint": "oxlint --fix && eslint --fix .",
|
"lint": "oxlint --fix && eslint --fix .",
|
||||||
"prepare": "simple-git-hooks",
|
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"release": "sa release",
|
"release": "sa release",
|
||||||
"typecheck": "vue-tsc --noEmit --skipLibCheck",
|
"typecheck": "vue-tsc --noEmit --skipLibCheck",
|
||||||
@@ -108,7 +107,6 @@
|
|||||||
"oxlint": "^1.64.0",
|
"oxlint": "^1.64.0",
|
||||||
"pro-naive-ui-resolver": "1.0.2",
|
"pro-naive-ui-resolver": "1.0.2",
|
||||||
"sass": "1.99.0",
|
"sass": "1.99.0",
|
||||||
"simple-git-hooks": "2.13.1",
|
|
||||||
"tsx": "4.21.0",
|
"tsx": "4.21.0",
|
||||||
"typescript": "6.0.3",
|
"typescript": "6.0.3",
|
||||||
"unocss": "^66.6.8",
|
"unocss": "^66.6.8",
|
||||||
@@ -122,10 +120,6 @@
|
|||||||
"vue-eslint-parser": "10.4.0",
|
"vue-eslint-parser": "10.4.0",
|
||||||
"vue-tsc": "3.2.8"
|
"vue-tsc": "3.2.8"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
|
||||||
"commit-msg": "pnpm sa git-commit-verify",
|
|
||||||
"pre-commit": "pnpm typecheck && pnpm lint && pnpm fmt && git diff --exit-code"
|
|
||||||
},
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.19.0",
|
"node": ">=20.19.0",
|
||||||
"pnpm": ">=10.5.0"
|
"pnpm": ">=10.5.0"
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "@sa/alova",
|
||||||
|
"version": "2.2.0",
|
||||||
|
"typesVersions": {
|
||||||
|
"*": {
|
||||||
|
"*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": "./src/index.ts",
|
||||||
|
"./fetch": "./src/fetch.ts",
|
||||||
|
"./client": "./src/client.ts",
|
||||||
|
"./mock": "./src/mock.ts"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@alova/mock": "2.0.20",
|
||||||
|
"@sa/utils": "workspace:*",
|
||||||
|
"alova": "3.5.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from 'alova/client';
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
/** the backend error code key */
|
||||||
|
export const BACKEND_ERROR_CODE = 'BACKEND_ERROR';
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
import adapterFetch from 'alova/fetch';
|
||||||
|
export default adapterFetch;
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { createAlova } from 'alova';
|
||||||
|
import type { AlovaDefaultCacheAdapter, AlovaGenerics, AlovaGlobalCacheAdapter, AlovaRequestAdapter } from 'alova';
|
||||||
|
import VueHook from 'alova/vue';
|
||||||
|
import type { VueHookType } from 'alova/vue';
|
||||||
|
import adapterFetch from 'alova/fetch';
|
||||||
|
import { createServerTokenAuthentication } from 'alova/client';
|
||||||
|
import type { FetchRequestInit } from 'alova/fetch';
|
||||||
|
import { BACKEND_ERROR_CODE } from './constant';
|
||||||
|
import type { CustomAlovaConfig, RequestOptions } from './type';
|
||||||
|
|
||||||
|
export const createAlovaRequest = <
|
||||||
|
RequestConfig = FetchRequestInit,
|
||||||
|
ResponseType = Response,
|
||||||
|
ResponseHeader = Headers,
|
||||||
|
L1Cache extends AlovaGlobalCacheAdapter = AlovaDefaultCacheAdapter,
|
||||||
|
L2Cache extends AlovaGlobalCacheAdapter = AlovaDefaultCacheAdapter
|
||||||
|
>(
|
||||||
|
customConfig: CustomAlovaConfig<
|
||||||
|
AlovaGenerics<any, any, RequestConfig, ResponseType, ResponseHeader, L1Cache, L2Cache, any>
|
||||||
|
>,
|
||||||
|
options: RequestOptions<AlovaGenerics<any, any, RequestConfig, ResponseType, ResponseHeader, L1Cache, L2Cache, any>>
|
||||||
|
) => {
|
||||||
|
const { tokenRefresher } = options;
|
||||||
|
const { onAuthRequired, onResponseRefreshToken } = createServerTokenAuthentication<
|
||||||
|
VueHookType,
|
||||||
|
AlovaRequestAdapter<RequestConfig, ResponseType, ResponseHeader>
|
||||||
|
>({
|
||||||
|
refreshTokenOnSuccess: {
|
||||||
|
isExpired: (response, method) => tokenRefresher?.isExpired(response, method) || false,
|
||||||
|
handler: async (response, method) => tokenRefresher?.handler(response, method)
|
||||||
|
},
|
||||||
|
refreshTokenOnError: {
|
||||||
|
isExpired: (response, method) => tokenRefresher?.isExpired(response, method) || false,
|
||||||
|
handler: async (response, method) => tokenRefresher?.handler(response, method)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const instance = createAlova({
|
||||||
|
...customConfig,
|
||||||
|
timeout: customConfig.timeout ?? 10 * 1000,
|
||||||
|
requestAdapter: (customConfig.requestAdapter as any) ?? adapterFetch(),
|
||||||
|
statesHook: VueHook,
|
||||||
|
beforeRequest: onAuthRequired(options.onRequest as any),
|
||||||
|
responded: onResponseRefreshToken({
|
||||||
|
onSuccess: async (response, method) => {
|
||||||
|
// check if http status is success
|
||||||
|
let error: any = null;
|
||||||
|
let transformedData: any = null;
|
||||||
|
try {
|
||||||
|
if (await options.isBackendSuccess(response)) {
|
||||||
|
transformedData = await options.transformBackendResponse(response);
|
||||||
|
} else {
|
||||||
|
error = new Error('the backend request error');
|
||||||
|
error.code = BACKEND_ERROR_CODE;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
error = err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
await options.onError?.(error, response, method);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformedData;
|
||||||
|
},
|
||||||
|
onComplete: options.onComplete,
|
||||||
|
onError: (error, method) => options.onError?.(error, null, method)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { BACKEND_ERROR_CODE };
|
||||||
|
export type * from './type';
|
||||||
|
export type * from 'alova';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from '@alova/mock';
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import type { AlovaGenerics, AlovaOptions, AlovaRequestAdapter, Method, ResponseCompleteHandler } from 'alova';
|
||||||
|
|
||||||
|
export type CustomAlovaConfig<AG extends AlovaGenerics> = Omit<
|
||||||
|
AlovaOptions<AG>,
|
||||||
|
'statesHook' | 'beforeRequest' | 'responded' | 'requestAdapter'
|
||||||
|
> & {
|
||||||
|
/** request adapter. all request of alova will be sent by it. */
|
||||||
|
requestAdapter?: AlovaRequestAdapter<AG['RequestConfig'], AG['Response'], AG['ResponseHeader']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface RequestOptions<AG extends AlovaGenerics> {
|
||||||
|
/**
|
||||||
|
* The hook before request
|
||||||
|
*
|
||||||
|
* For example: You can add header token in this hook
|
||||||
|
*
|
||||||
|
* @param method alova Method Instance
|
||||||
|
*/
|
||||||
|
onRequest?: AlovaOptions<AG>['beforeRequest'];
|
||||||
|
/**
|
||||||
|
* The hook to check backend response is success or not
|
||||||
|
*
|
||||||
|
* @param response alova response
|
||||||
|
*/
|
||||||
|
isBackendSuccess: (response: AG['Response']) => Promise<boolean>;
|
||||||
|
|
||||||
|
/** The config to refresh token */
|
||||||
|
tokenRefresher?: {
|
||||||
|
/** detect the token is expired */
|
||||||
|
isExpired(response: AG['Response'], Method: Method<AG>): Promise<boolean> | boolean;
|
||||||
|
/** refresh token handler */
|
||||||
|
handler(response: AG['Response'], Method: Method<AG>): Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The hook after backend request complete */
|
||||||
|
onComplete?: ResponseCompleteHandler<AG>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hook to handle error
|
||||||
|
*
|
||||||
|
* For example: You can show error message in this hook
|
||||||
|
*
|
||||||
|
* @param error
|
||||||
|
*/
|
||||||
|
onError?: (error: any, response: AG['Response'] | null, methodInstance: Method<AG>) => any | Promise<any>;
|
||||||
|
/**
|
||||||
|
* transform backend response when the responseType is json
|
||||||
|
*
|
||||||
|
* @param response alova response
|
||||||
|
*/
|
||||||
|
transformBackendResponse: (response: AG['Response']) => any;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"jsx": "preserve",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"types": ["node"],
|
||||||
|
"strict": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
Generated
-9
@@ -195,9 +195,6 @@ importers:
|
|||||||
sass:
|
sass:
|
||||||
specifier: 1.99.0
|
specifier: 1.99.0
|
||||||
version: 1.99.0
|
version: 1.99.0
|
||||||
simple-git-hooks:
|
|
||||||
specifier: 2.13.1
|
|
||||||
version: 2.13.1
|
|
||||||
tsx:
|
tsx:
|
||||||
specifier: 4.21.0
|
specifier: 4.21.0
|
||||||
version: 4.21.0
|
version: 4.21.0
|
||||||
@@ -4705,10 +4702,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
simple-git-hooks@2.13.1:
|
|
||||||
resolution: {integrity: sha512-WszCLXwT4h2k1ufIXAgsbiTOazqqevFCIncOuUBZJ91DdvWcC5+OFkluWRQPrcuSYd8fjq+o2y1QfWqYMoAToQ==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
simple-statistics@6.1.0:
|
simple-statistics@6.1.0:
|
||||||
resolution: {integrity: sha512-Vi/xPPuiEIizXOCDx3N8LjcIqC7Z8euiIfvmj5oYimm9/KmXNKeK4aHiVMeE9q7e9wfg1i9YRoWnUNURq54ZFg==}
|
resolution: {integrity: sha512-Vi/xPPuiEIizXOCDx3N8LjcIqC7Z8euiIfvmj5oYimm9/KmXNKeK4aHiVMeE9q7e9wfg1i9YRoWnUNURq54ZFg==}
|
||||||
|
|
||||||
@@ -10139,8 +10132,6 @@ snapshots:
|
|||||||
|
|
||||||
signal-exit@4.1.0: {}
|
signal-exit@4.1.0: {}
|
||||||
|
|
||||||
simple-git-hooks@2.13.1: {}
|
|
||||||
|
|
||||||
simple-statistics@6.1.0: {}
|
simple-statistics@6.1.0: {}
|
||||||
|
|
||||||
simple-statistics@7.8.9: {}
|
simple-statistics@7.8.9: {}
|
||||||
|
|||||||
@@ -12,10 +12,6 @@ export const themeSchemaRecord: Record<UnionKey.ThemeScheme, App.I18n.I18nKey> =
|
|||||||
|
|
||||||
export const themeSchemaOptions = transformRecordToOption(themeSchemaRecord);
|
export const themeSchemaOptions = transformRecordToOption(themeSchemaRecord);
|
||||||
|
|
||||||
export const loginModuleRecord: Record<UnionKey.LoginModule, App.I18n.I18nKey> = {
|
|
||||||
'pwd-login': 'page.login.pwdLogin.title',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const themeLayoutModeRecord: Record<UnionKey.ThemeLayoutMode, App.I18n.I18nKey> = {
|
export const themeLayoutModeRecord: Record<UnionKey.ThemeLayoutMode, App.I18n.I18nKey> = {
|
||||||
vertical: 'theme.layout.layoutMode.vertical',
|
vertical: 'theme.layout.layoutMode.vertical',
|
||||||
'vertical-mix': 'theme.layout.layoutMode.vertical-mix',
|
'vertical-mix': 'theme.layout.layoutMode.vertical-mix',
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
import { computed } from 'vue';
|
|
||||||
import { useCountDown, useLoading } from '@sa/hooks';
|
|
||||||
import { REG_PHONE } from '@/constants/reg';
|
|
||||||
import { $t } from '@/locales';
|
|
||||||
|
|
||||||
export function useCaptcha() {
|
|
||||||
const { loading, startLoading, endLoading } = useLoading();
|
|
||||||
const { count, start, stop, isCounting } = useCountDown(10);
|
|
||||||
|
|
||||||
const label = computed(() => {
|
|
||||||
let text = $t('page.login.codeLogin.getCode');
|
|
||||||
|
|
||||||
const countingLabel = $t('page.login.codeLogin.reGetCode', { time: count.value });
|
|
||||||
|
|
||||||
if (loading.value) {
|
|
||||||
text = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCounting.value) {
|
|
||||||
text = countingLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
});
|
|
||||||
|
|
||||||
function isPhoneValid(phone: string) {
|
|
||||||
if (phone.trim() === '') {
|
|
||||||
window.$message?.error?.($t('form.phone.required'));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!REG_PHONE.test(phone)) {
|
|
||||||
window.$message?.error?.($t('form.phone.invalid'));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getCaptcha(phone: string) {
|
|
||||||
const valid = isPhoneValid(phone);
|
|
||||||
|
|
||||||
if (!valid || loading.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
startLoading();
|
|
||||||
|
|
||||||
// request
|
|
||||||
await new Promise(resolve => {
|
|
||||||
setTimeout(resolve, 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
window.$message?.success?.($t('page.login.codeLogin.sendCodeSuccess'));
|
|
||||||
|
|
||||||
start();
|
|
||||||
|
|
||||||
endLoading();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
label,
|
|
||||||
start,
|
|
||||||
stop,
|
|
||||||
isCounting,
|
|
||||||
loading,
|
|
||||||
getCaptcha
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,6 @@ import type { VNode } from 'vue';
|
|||||||
import { useAuthStore } from '@/store/modules/auth';
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
import { useRouterPush } from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
import { useSvgIcon } from '@/hooks/common/icon';
|
import { useSvgIcon } from '@/hooks/common/icon';
|
||||||
import { $t } from '@/locales';
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'UserAvatar'
|
name: 'UserAvatar'
|
||||||
@@ -34,7 +33,7 @@ type DropdownOption =
|
|||||||
const options = computed(() => {
|
const options = computed(() => {
|
||||||
const opts: DropdownOption[] = [
|
const opts: DropdownOption[] = [
|
||||||
{
|
{
|
||||||
label: $t('common.userCenter'),
|
label: '个人中心',
|
||||||
key: 'user-center',
|
key: 'user-center',
|
||||||
icon: SvgIconVNode({ icon: 'ph:user-circle', fontSize: 18 })
|
icon: SvgIconVNode({ icon: 'ph:user-circle', fontSize: 18 })
|
||||||
},
|
},
|
||||||
@@ -43,7 +42,7 @@ const options = computed(() => {
|
|||||||
key: 'divider'
|
key: 'divider'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: $t('common.logout'),
|
label: '退出登录',
|
||||||
key: 'logout',
|
key: 'logout',
|
||||||
icon: SvgIconVNode({ icon: 'ph:sign-out', fontSize: 18 })
|
icon: SvgIconVNode({ icon: 'ph:sign-out', fontSize: 18 })
|
||||||
}
|
}
|
||||||
@@ -54,10 +53,10 @@ const options = computed(() => {
|
|||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
window.$dialog?.info({
|
window.$dialog?.info({
|
||||||
title: $t('common.tip'),
|
title: '提示',
|
||||||
content: $t('common.logoutConfirm'),
|
content: '确定退出登录吗?',
|
||||||
positiveText: $t('common.confirm'),
|
positiveText: '确定',
|
||||||
negativeText: $t('common.cancel'),
|
negativeText: '取消',
|
||||||
onPositiveClick: () => {
|
onPositiveClick: () => {
|
||||||
authStore.resetStore();
|
authStore.resetStore();
|
||||||
}
|
}
|
||||||
@@ -69,14 +68,14 @@ function handleDropdown(key: DropdownKey) {
|
|||||||
logout();
|
logout();
|
||||||
} else {
|
} else {
|
||||||
// If your other options are jumps from other routes, they will be directly supported here
|
// If your other options are jumps from other routes, they will be directly supported here
|
||||||
routerPushByKey(key);
|
// routerPushByKey(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NButton v-if="!authStore.isLogin" quaternary @click="loginOrRegister">
|
<NButton v-if="!authStore.isLogin" quaternary @click="loginOrRegister">
|
||||||
{{ $t('page.login.common.loginOrRegister') }}
|
登录/注册
|
||||||
</NButton>
|
</NButton>
|
||||||
<NDropdown v-else placement="bottom" trigger="click" :options="options" @select="handleDropdown">
|
<NDropdown v-else placement="bottom" trigger="click" :options="options" @select="handleDropdown">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
+10
-76
@@ -229,82 +229,16 @@ const local: App.I18n.Schema = {
|
|||||||
404: 'Page Not Found',
|
404: 'Page Not Found',
|
||||||
500: 'Server Error',
|
500: 'Server Error',
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
'user-center': 'User Center',
|
home_index: '工作台首页',
|
||||||
},
|
home_initiatechange: '发起变更',
|
||||||
page: {
|
home_mydraft: '我的草稿',
|
||||||
login: {
|
home_pending: '待我处理',
|
||||||
common: {
|
home_process: '流程演示',
|
||||||
loginOrRegister: 'Login / Register',
|
home_processdetail: '流程演示详情',
|
||||||
userNamePlaceholder: 'Please enter user name',
|
changeledger: '变更台账',
|
||||||
phonePlaceholder: 'Please enter phone number',
|
changeledger_mychanges: '我发起的变更',
|
||||||
codePlaceholder: 'Please enter verification code',
|
changeledger_workshopchanges: '本车间变更',
|
||||||
passwordPlaceholder: 'Please enter password',
|
changestatistics: '本部门变更统计',
|
||||||
confirmPasswordPlaceholder: 'Please enter password again',
|
|
||||||
codeLogin: 'Verification code login',
|
|
||||||
confirm: 'Confirm',
|
|
||||||
back: 'Back',
|
|
||||||
validateSuccess: 'Verification passed',
|
|
||||||
loginSuccess: 'Login successfully',
|
|
||||||
welcomeBack: 'Welcome back, {userName} !'
|
|
||||||
},
|
|
||||||
pwdLogin: {
|
|
||||||
title: 'Password Login',
|
|
||||||
rememberMe: 'Remember me',
|
|
||||||
forgetPassword: 'Forget password?',
|
|
||||||
register: 'Register',
|
|
||||||
otherAccountLogin: 'Other Account Login',
|
|
||||||
otherLoginMode: 'Other Login Mode',
|
|
||||||
superAdmin: 'Super Admin',
|
|
||||||
admin: 'Admin',
|
|
||||||
user: 'User'
|
|
||||||
},
|
|
||||||
codeLogin: {
|
|
||||||
title: 'Verification Code Login',
|
|
||||||
getCode: 'Get verification code',
|
|
||||||
reGetCode: 'Reacquire after {time}s',
|
|
||||||
sendCodeSuccess: 'Verification code sent successfully',
|
|
||||||
imageCodePlaceholder: 'Please enter image verification code'
|
|
||||||
},
|
|
||||||
register: {
|
|
||||||
title: 'Register',
|
|
||||||
agreement: 'I have read and agree to',
|
|
||||||
protocol: '《User Agreement》',
|
|
||||||
policy: '《Privacy Policy》'
|
|
||||||
},
|
|
||||||
resetPwd: {
|
|
||||||
title: 'Reset Password'
|
|
||||||
},
|
|
||||||
bindWeChat: {
|
|
||||||
title: 'Bind WeChat'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
home: {
|
|
||||||
branchDesc:
|
|
||||||
'For the convenience of everyone in developing and updating the merge, we have streamlined the code of the main branch, only retaining the homepage menu, and the rest of the content has been moved to the example branch for maintenance. The preview address displays the content of the example branch.',
|
|
||||||
projectCount: 'Project Count',
|
|
||||||
todo: 'Todo',
|
|
||||||
message: 'Message',
|
|
||||||
downloadCount: 'Download Count',
|
|
||||||
registerCount: 'Register Count',
|
|
||||||
schedule: 'Work and rest Schedule',
|
|
||||||
study: 'Study',
|
|
||||||
work: 'Work',
|
|
||||||
rest: 'Rest',
|
|
||||||
entertainment: 'Entertainment',
|
|
||||||
visitCount: 'Visit Count',
|
|
||||||
turnover: 'Turnover',
|
|
||||||
dealCount: 'Deal Count',
|
|
||||||
projectNews: {
|
|
||||||
title: 'Project News',
|
|
||||||
moreNews: 'More News',
|
|
||||||
desc1: 'Soybean created the open source project soybean-admin on May 28, 2021!',
|
|
||||||
desc2: 'Yanbowe submitted a bug to soybean-admin, the multi-tab bar will not adapt.',
|
|
||||||
desc3: 'Soybean is ready to do sufficient preparation for the release of soybean-admin!',
|
|
||||||
desc4: 'Soybean is busy writing project documentation for soybean-admin!',
|
|
||||||
desc5: 'Soybean just wrote some of the workbench pages casually, and it was enough to see!'
|
|
||||||
},
|
|
||||||
creativity: 'Creativity'
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
required: 'Cannot be empty',
|
required: 'Cannot be empty',
|
||||||
|
|||||||
@@ -235,17 +235,6 @@ const local: App.I18n.Schema = {
|
|||||||
changeledger_mychanges: '我发起的变更',
|
changeledger_mychanges: '我发起的变更',
|
||||||
changeledger_workshopchanges: '本车间变更',
|
changeledger_workshopchanges: '本车间变更',
|
||||||
changestatistics: '本部门变更统计',
|
changestatistics: '本部门变更统计',
|
||||||
'user-center': '个人中心',
|
|
||||||
},
|
|
||||||
page: {
|
|
||||||
login: {
|
|
||||||
common: {
|
|
||||||
confirm: '确定',
|
|
||||||
back: '返回',
|
|
||||||
loginSuccess: '登录成功',
|
|
||||||
welcomeBack: '欢迎回来,{userName} !'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
required: '不能为空',
|
required: '不能为空',
|
||||||
|
|||||||
@@ -28,5 +28,4 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
home_process: () => import("@/views/home/process/index.vue"),
|
home_process: () => import("@/views/home/process/index.vue"),
|
||||||
home_processdetail: () => import("@/views/home/processDetail/index.vue"),
|
home_processdetail: () => import("@/views/home/processDetail/index.vue"),
|
||||||
login: () => import("@/views/login/index.vue"),
|
login: () => import("@/views/login/index.vue"),
|
||||||
"user-center": () => import("@/views/user-center/index.vue"),
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -169,15 +169,5 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
constant: true,
|
constant: true,
|
||||||
hideInMenu: true
|
hideInMenu: true
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'user-center',
|
|
||||||
path: '/user-center',
|
|
||||||
component: 'layout.base$view.user-center',
|
|
||||||
meta: {
|
|
||||||
title: 'user-center',
|
|
||||||
i18nKey: 'route.user-center',
|
|
||||||
hideInMenu: true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -177,8 +177,7 @@ const routeMap: RouteMap = {
|
|||||||
"home_pending": "/home/pending",
|
"home_pending": "/home/pending",
|
||||||
"home_process": "/home/process",
|
"home_process": "/home/process",
|
||||||
"home_processdetail": "/home/processdetail",
|
"home_processdetail": "/home/processdetail",
|
||||||
"login": "/login/:module(pwd-login)?",
|
"login": "/login/:module(pwd-login)?"
|
||||||
"user-center": "/user-center"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { CustomRoute, ElegantConstRoute, ElegantRoute } from '@elegant-router/types';
|
import type { ElegantConstRoute, ElegantRoute } from '@elegant-router/types';
|
||||||
import { generatedRoutes } from '../elegant/routes';
|
import { generatedRoutes } from '../elegant/routes';
|
||||||
import { layouts, views } from '../elegant/imports';
|
import { layouts, views } from '../elegant/imports';
|
||||||
import { transformElegantRoutesToVueRoutes } from '../elegant/transform';
|
import { transformElegantRoutesToVueRoutes } from '../elegant/transform';
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { fetchGetUserInfo, fetchLogin } from '@/service/api';
|
|||||||
import { useRouterPush } from '@/hooks/common/router';
|
import { useRouterPush } from '@/hooks/common/router';
|
||||||
import { localStg } from '@/utils/storage';
|
import { localStg } from '@/utils/storage';
|
||||||
import { SetupStoreId } from '@/enum';
|
import { SetupStoreId } from '@/enum';
|
||||||
import { $t } from '@/locales';
|
|
||||||
import { useRouteStore } from '../route';
|
import { useRouteStore } from '../route';
|
||||||
import { useTabStore } from '../tab';
|
import { useTabStore } from '../tab';
|
||||||
import { clearAuthStorage, getToken } from './shared';
|
import { clearAuthStorage, getToken } from './shared';
|
||||||
@@ -116,8 +115,8 @@ export const useAuthStore = defineStore(SetupStoreId.Auth, () => {
|
|||||||
await redirectFromLogin(needRedirect);
|
await redirectFromLogin(needRedirect);
|
||||||
|
|
||||||
window.$notification?.success({
|
window.$notification?.success({
|
||||||
title: $t('page.login.common.loginSuccess'),
|
title: '登录成功',
|
||||||
content: $t('page.login.common.welcomeBack', { userName: userInfo.userName }),
|
content: `欢迎回来,${userInfo.userName} !`,
|
||||||
duration: 4500
|
duration: 4500
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
-334
@@ -480,340 +480,6 @@ declare namespace App {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
route: Record<I18nRouteKey, string>;
|
route: Record<I18nRouteKey, string>;
|
||||||
page: {
|
|
||||||
login: {
|
|
||||||
common: {
|
|
||||||
loginOrRegister: string;
|
|
||||||
userNamePlaceholder: string;
|
|
||||||
phonePlaceholder: string;
|
|
||||||
codePlaceholder: string;
|
|
||||||
passwordPlaceholder: string;
|
|
||||||
confirmPasswordPlaceholder: string;
|
|
||||||
codeLogin: string;
|
|
||||||
confirm: string;
|
|
||||||
back: string;
|
|
||||||
validateSuccess: string;
|
|
||||||
loginSuccess: string;
|
|
||||||
welcomeBack: string;
|
|
||||||
};
|
|
||||||
pwdLogin: {
|
|
||||||
title: string;
|
|
||||||
rememberMe: string;
|
|
||||||
forgetPassword: string;
|
|
||||||
register: string;
|
|
||||||
otherAccountLogin: string;
|
|
||||||
otherLoginMode: string;
|
|
||||||
superAdmin: string;
|
|
||||||
admin: string;
|
|
||||||
user: string;
|
|
||||||
};
|
|
||||||
codeLogin: {
|
|
||||||
title: string;
|
|
||||||
getCode: string;
|
|
||||||
reGetCode: string;
|
|
||||||
sendCodeSuccess: string;
|
|
||||||
imageCodePlaceholder: string;
|
|
||||||
};
|
|
||||||
register: {
|
|
||||||
title: string;
|
|
||||||
agreement: string;
|
|
||||||
protocol: string;
|
|
||||||
policy: string;
|
|
||||||
};
|
|
||||||
resetPwd: {
|
|
||||||
title: string;
|
|
||||||
};
|
|
||||||
bindWeChat: {
|
|
||||||
title: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
about: {
|
|
||||||
title: string;
|
|
||||||
introduction: string;
|
|
||||||
projectInfo: {
|
|
||||||
title: string;
|
|
||||||
version: string;
|
|
||||||
latestBuildTime: string;
|
|
||||||
githubLink: string;
|
|
||||||
previewLink: string;
|
|
||||||
};
|
|
||||||
prdDep: string;
|
|
||||||
devDep: string;
|
|
||||||
};
|
|
||||||
home: {
|
|
||||||
branchDesc: string;
|
|
||||||
projectCount: string;
|
|
||||||
todo: string;
|
|
||||||
message: string;
|
|
||||||
downloadCount: string;
|
|
||||||
registerCount: string;
|
|
||||||
schedule: string;
|
|
||||||
study: string;
|
|
||||||
work: string;
|
|
||||||
rest: string;
|
|
||||||
entertainment: string;
|
|
||||||
visitCount: string;
|
|
||||||
turnover: string;
|
|
||||||
dealCount: string;
|
|
||||||
projectNews: {
|
|
||||||
title: string;
|
|
||||||
moreNews: string;
|
|
||||||
desc1: string;
|
|
||||||
desc2: string;
|
|
||||||
desc3: string;
|
|
||||||
desc4: string;
|
|
||||||
desc5: string;
|
|
||||||
};
|
|
||||||
creativity: string;
|
|
||||||
};
|
|
||||||
function: {
|
|
||||||
tab: {
|
|
||||||
tabOperate: {
|
|
||||||
title: string;
|
|
||||||
addTab: string;
|
|
||||||
addTabDesc: string;
|
|
||||||
closeTab: string;
|
|
||||||
closeCurrentTab: string;
|
|
||||||
closeAboutTab: string;
|
|
||||||
addMultiTab: string;
|
|
||||||
addMultiTabDesc1: string;
|
|
||||||
addMultiTabDesc2: string;
|
|
||||||
};
|
|
||||||
tabTitle: {
|
|
||||||
title: string;
|
|
||||||
changeTitle: string;
|
|
||||||
change: string;
|
|
||||||
resetTitle: string;
|
|
||||||
reset: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
multiTab: {
|
|
||||||
routeParam: string;
|
|
||||||
backTab: string;
|
|
||||||
};
|
|
||||||
toggleAuth: {
|
|
||||||
toggleAccount: string;
|
|
||||||
authHook: string;
|
|
||||||
superAdminVisible: string;
|
|
||||||
adminVisible: string;
|
|
||||||
adminOrUserVisible: string;
|
|
||||||
};
|
|
||||||
request: {
|
|
||||||
repeatedErrorOccurOnce: string;
|
|
||||||
repeatedError: string;
|
|
||||||
repeatedErrorMsg1: string;
|
|
||||||
repeatedErrorMsg2: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
alova: {
|
|
||||||
scenes: {
|
|
||||||
captchaSend: string;
|
|
||||||
autoRequest: string;
|
|
||||||
visibilityRequestTips: string;
|
|
||||||
pollingRequestTips: string;
|
|
||||||
networkRequestTips: string;
|
|
||||||
refreshTime: string;
|
|
||||||
startRequest: string;
|
|
||||||
stopRequest: string;
|
|
||||||
requestCrossComponent: string;
|
|
||||||
triggerAllRequest: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
proNaive: {
|
|
||||||
form: {
|
|
||||||
basic: {
|
|
||||||
title: string;
|
|
||||||
appName: string;
|
|
||||||
appStatus: string;
|
|
||||||
createTime: string;
|
|
||||||
responseDate: string;
|
|
||||||
specificationInfo: string;
|
|
||||||
specificate: string;
|
|
||||||
specificationName: string;
|
|
||||||
specificationValue: string;
|
|
||||||
specificationColorRed: string;
|
|
||||||
specificationColorOrange: string;
|
|
||||||
addSpecificateItem: string;
|
|
||||||
fillValue: string;
|
|
||||||
reset: string;
|
|
||||||
submit: string;
|
|
||||||
add: string;
|
|
||||||
delete: string;
|
|
||||||
color: string;
|
|
||||||
normal: string;
|
|
||||||
anomaly: string;
|
|
||||||
};
|
|
||||||
query: {
|
|
||||||
title1: string;
|
|
||||||
title2: string;
|
|
||||||
appName: string;
|
|
||||||
appStatus: string;
|
|
||||||
createTime: string;
|
|
||||||
responseDate: string;
|
|
||||||
endDate: string;
|
|
||||||
field: string;
|
|
||||||
};
|
|
||||||
step: {
|
|
||||||
title: string;
|
|
||||||
step1: {
|
|
||||||
title: string;
|
|
||||||
field: string;
|
|
||||||
nextStep: string;
|
|
||||||
};
|
|
||||||
step2: {
|
|
||||||
title: string;
|
|
||||||
field: string;
|
|
||||||
prevStep: string;
|
|
||||||
submit: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
table: {
|
|
||||||
remote: {
|
|
||||||
filterCondition: string;
|
|
||||||
name: string;
|
|
||||||
createTime: string;
|
|
||||||
responseTime: string;
|
|
||||||
title: string;
|
|
||||||
replicableText: string;
|
|
||||||
tags: string;
|
|
||||||
dateFormatting: string;
|
|
||||||
image: string;
|
|
||||||
};
|
|
||||||
rowEdit: {
|
|
||||||
title: string;
|
|
||||||
reset: string;
|
|
||||||
submit: string;
|
|
||||||
edit: string;
|
|
||||||
delete: string;
|
|
||||||
save: string;
|
|
||||||
task: string;
|
|
||||||
score: string;
|
|
||||||
time: string;
|
|
||||||
name: string;
|
|
||||||
action: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
manage: {
|
|
||||||
common: {
|
|
||||||
status: {
|
|
||||||
enable: string;
|
|
||||||
disable: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
role: {
|
|
||||||
title: string;
|
|
||||||
roleName: string;
|
|
||||||
roleCode: string;
|
|
||||||
roleStatus: string;
|
|
||||||
roleDesc: string;
|
|
||||||
form: {
|
|
||||||
roleName: string;
|
|
||||||
roleCode: string;
|
|
||||||
roleStatus: string;
|
|
||||||
roleDesc: string;
|
|
||||||
};
|
|
||||||
addRole: string;
|
|
||||||
editRole: string;
|
|
||||||
menuAuth: string;
|
|
||||||
buttonAuth: string;
|
|
||||||
};
|
|
||||||
user: {
|
|
||||||
title: string;
|
|
||||||
userName: string;
|
|
||||||
userGender: string;
|
|
||||||
nickName: string;
|
|
||||||
userPhone: string;
|
|
||||||
userEmail: string;
|
|
||||||
userStatus: string;
|
|
||||||
userRole: string;
|
|
||||||
form: {
|
|
||||||
userName: string;
|
|
||||||
userGender: string;
|
|
||||||
nickName: string;
|
|
||||||
userPhone: string;
|
|
||||||
userEmail: string;
|
|
||||||
userStatus: string;
|
|
||||||
userRole: string;
|
|
||||||
};
|
|
||||||
addUser: string;
|
|
||||||
editUser: string;
|
|
||||||
gender: {
|
|
||||||
male: string;
|
|
||||||
female: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
menu: {
|
|
||||||
home: string;
|
|
||||||
title: string;
|
|
||||||
id: string;
|
|
||||||
parentId: string;
|
|
||||||
menuType: string;
|
|
||||||
menuName: string;
|
|
||||||
routeName: string;
|
|
||||||
routePath: string;
|
|
||||||
pathParam: string;
|
|
||||||
layout: string;
|
|
||||||
page: string;
|
|
||||||
i18nKey: string;
|
|
||||||
icon: string;
|
|
||||||
localIcon: string;
|
|
||||||
iconTypeTitle: string;
|
|
||||||
order: string;
|
|
||||||
constant: string;
|
|
||||||
keepAlive: string;
|
|
||||||
href: string;
|
|
||||||
hideInMenu: string;
|
|
||||||
activeMenu: string;
|
|
||||||
multiTab: string;
|
|
||||||
fixedIndexInTab: string;
|
|
||||||
query: string;
|
|
||||||
button: string;
|
|
||||||
buttonCode: string;
|
|
||||||
buttonDesc: string;
|
|
||||||
menuStatus: string;
|
|
||||||
form: {
|
|
||||||
home: string;
|
|
||||||
menuType: string;
|
|
||||||
menuName: string;
|
|
||||||
routeName: string;
|
|
||||||
routePath: string;
|
|
||||||
pathParam: string;
|
|
||||||
layout: string;
|
|
||||||
page: string;
|
|
||||||
i18nKey: string;
|
|
||||||
icon: string;
|
|
||||||
localIcon: string;
|
|
||||||
order: string;
|
|
||||||
keepAlive: string;
|
|
||||||
href: string;
|
|
||||||
hideInMenu: string;
|
|
||||||
activeMenu: string;
|
|
||||||
multiTab: string;
|
|
||||||
fixedInTab: string;
|
|
||||||
fixedIndexInTab: string;
|
|
||||||
queryKey: string;
|
|
||||||
queryValue: string;
|
|
||||||
button: string;
|
|
||||||
buttonCode: string;
|
|
||||||
buttonDesc: string;
|
|
||||||
menuStatus: string;
|
|
||||||
};
|
|
||||||
addMenu: string;
|
|
||||||
editMenu: string;
|
|
||||||
addChildMenu: string;
|
|
||||||
type: {
|
|
||||||
directory: string;
|
|
||||||
menu: string;
|
|
||||||
};
|
|
||||||
iconType: {
|
|
||||||
iconify: string;
|
|
||||||
local: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
form: {
|
form: {
|
||||||
required: string;
|
required: string;
|
||||||
userName: FormMsg;
|
userName: FormMsg;
|
||||||
|
|||||||
Vendored
-3
@@ -32,7 +32,6 @@ declare module "@elegant-router/types" {
|
|||||||
"home_process": "/home/process";
|
"home_process": "/home/process";
|
||||||
"home_processdetail": "/home/processdetail";
|
"home_processdetail": "/home/processdetail";
|
||||||
"login": "/login/:module(pwd-login)?";
|
"login": "/login/:module(pwd-login)?";
|
||||||
"user-center": "/user-center";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +70,6 @@ declare module "@elegant-router/types" {
|
|||||||
| "changestatistics"
|
| "changestatistics"
|
||||||
| "home"
|
| "home"
|
||||||
| "login"
|
| "login"
|
||||||
| "user-center"
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,7 +99,6 @@ declare module "@elegant-router/types" {
|
|||||||
| "home_process"
|
| "home_process"
|
||||||
| "home_processdetail"
|
| "home_processdetail"
|
||||||
| "login"
|
| "login"
|
||||||
| "user-center"
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,14 +33,13 @@ const ROLES = [
|
|||||||
{ id: "viewer", name: "非审批人员", person: "吴新", org: "相关部门", desc: "以信息查看为主,不参与变更流程" },
|
{ id: "viewer", name: "非审批人员", person: "吴新", org: "相关部门", desc: "以信息查看为主,不参与变更流程" },
|
||||||
];
|
];
|
||||||
const mine = computed(() => CHANGES.filter((c) => c.applicant === ROLES[0].person));
|
const mine = computed(() => CHANGES.filter((c) => c.applicant === ROLES[0].person));
|
||||||
interface MyRow { c: ChangeOrder | null; id: string; title: string; type: ChangeType; level: ChangeLevel; status: ChangeStatus; date: string; urgent: boolean; duration: "永久" | "临时" }
|
|
||||||
const myRows = computed(() => [
|
const myRows = computed(() => [
|
||||||
...mine.value.map((c:ChangeOrder) => ({ c, id: c.id, title: c.title, type: c.type, level: c.level, status: c.status, date: c.date, urgent: c.urgent, duration: c.duration })),
|
...mine.value.map((c:ChangeOrder) => ({ c, id: c.id, title: c.title, type: c.type, level: c.level, status: c.status, date: c.date, urgent: c.urgent, duration: c.duration })),
|
||||||
...MY_CLOSED.map((m) => ({ c: null, ...m, urgent: false })),
|
...MY_CLOSED.map((m) => ({ c: null, ...m, urgent: false })),
|
||||||
]);
|
]);
|
||||||
const BIG_STAGES = ["申请审批", "实施与关闭", "变更关闭"];
|
const BIG_STAGES = ["申请审批", "实施与关闭", "变更关闭"];
|
||||||
const bigStageOf = (s: ChangeStatus) => (s === "审批中" ? 0 : s === "已关闭" ? 2 : 1);
|
const bigStageOf = (s: any) => (s === "审批中" ? 0 : s === "已关闭" ? 2 : 1);
|
||||||
const openRow = (row: MyRow) => {
|
const openRow = (row: any) => {
|
||||||
if (row.c){
|
if (row.c){
|
||||||
emit("openChange", row.c);
|
emit("openChange", row.c);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
CHANGES, DOC_TODO, LEVEL_COLOR, STATUS_COLOR, TEMP_WATCH, URGE_RECORDS,
|
CHANGES, DOC_TODO, LEVEL_COLOR, STATUS_COLOR, TEMP_WATCH, URGE_RECORDS,
|
||||||
countOpenStatus, type ChangeLevel, type ChangeOrder, type ChangeStatus, type ChangeType,
|
countOpenStatus, type ChangeLevel, type ChangeOrder, type ChangeStatus, type ChangeType,
|
||||||
} from "@/typings/model";
|
} from "@/typings/model";
|
||||||
|
import { getColorWithOpacity } from "@/utils/common";
|
||||||
|
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ const form = ref<ApplyForm>({
|
|||||||
name: "", dept: "", mainChanges: [""], related: "", purposes: [], effect: "",
|
name: "", dept: "", mainChanges: [""], related: "", purposes: [], effect: "",
|
||||||
type: "", level: "", duration: "", urgent: false, date: "", restoreDate: "",
|
type: "", level: "", duration: "", urgent: false, date: "", restoreDate: "",
|
||||||
});
|
});
|
||||||
|
const tab = ref<string>("pre");
|
||||||
const TABS = [
|
const TABS = [
|
||||||
{ id: "pre", name: "变更预识别", icon: 'lucide:sparkles' },
|
{ id: "pre", name: "变更预识别", icon: 'lucide:sparkles' },
|
||||||
{ id: "form", name: "变更申请表", icon: 'akar-icons:file' },
|
{ id: "form", name: "变更申请表", icon: 'akar-icons:file' },
|
||||||
@@ -36,8 +38,7 @@ const TABS = [
|
|||||||
{ id: "accept", name: "验收评价", icon: 'material-symbols:check-circle-outline' },
|
{ id: "accept", name: "验收评价", icon: 'material-symbols:check-circle-outline' },
|
||||||
{ id: "close", name: "变更关闭确认表", icon: 'quill:folder-open' },
|
{ id: "close", name: "变更关闭确认表", icon: 'quill:folder-open' },
|
||||||
];
|
];
|
||||||
const tab = ref<"pre" | "form" | "risk" | "train" | "pssr" | "accept" | "close">("pre");
|
const formGen = ref<string>("idle");
|
||||||
const formGen = ref<"idle" | "generating" | "done">("idle");
|
|
||||||
const confirmed = ref<Record<string, boolean>>({});
|
const confirmed = ref<Record<string, boolean>>({});
|
||||||
const blockedTabs = ref<string[]>([]);
|
const blockedTabs = ref<string[]>([]);
|
||||||
|
|
||||||
@@ -47,10 +48,16 @@ const blockedTabs = ref<string[]>([]);
|
|||||||
<NSpace vertical :size="16">
|
<NSpace vertical :size="16">
|
||||||
<!-- 发起变更 -->
|
<!-- 发起变更 -->
|
||||||
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
|
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
|
||||||
<div class="sticky top-0 z-20 rounded-t-xl border-b bg-[#e8f2fd]">
|
<div
|
||||||
|
class="sticky top-0 z-20 border-b bg-[var(--bg-color)]"
|
||||||
|
:style="{
|
||||||
|
borderRadius: themeStore.themeRadius + 'px',
|
||||||
|
'--bg-color': getColorWithOpacity(themeStore.themeColor, 0.1)
|
||||||
|
}"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="flex flex-wrap items-center gap-x-3 gap-y-2 border-b px-4 py-2"
|
class="flex flex-wrap items-center gap-x-3 gap-y-2 border-b px-4 py-2 border-[var(--border-color)]"
|
||||||
:style="{borderColor: themeStore.themeColor}"
|
:style="{'--border-color': getColorWithOpacity(themeStore.themeColor, 0.2)}"
|
||||||
>
|
>
|
||||||
<span class="whitespace-nowrap text-sm font-medium text-slate-600">变更名称 <span class="text-red-500">*</span></span>
|
<span class="whitespace-nowrap text-sm font-medium text-slate-600">变更名称 <span class="text-red-500">*</span></span>
|
||||||
<NInput v-model:value="form.name" maxlength="28" show-count placeholder="AI 自动总结(28 字以内),可手动修改" class="!w-420px" />
|
<NInput v-model:value="form.name" maxlength="28" show-count placeholder="AI 自动总结(28 字以内),可手动修改" class="!w-420px" />
|
||||||
@@ -60,8 +67,11 @@ const blockedTabs = ref<string[]>([]);
|
|||||||
<div class="flex items-center gap-1 overflow-x-auto px-3 pt-2">
|
<div class="flex items-center gap-1 overflow-x-auto px-3 pt-2">
|
||||||
<div v-for="t in TABS" :key="t.id" @click="tab = t.id"
|
<div v-for="t in TABS" :key="t.id" @click="tab = t.id"
|
||||||
class="flex items-center gap-1.5 whitespace-nowrap px-3 py-2 text-sm transition cursor-pointer border hover:bg-white/60 rounded-t-lg"
|
class="flex items-center gap-1.5 whitespace-nowrap px-3 py-2 text-sm transition cursor-pointer border hover:bg-white/60 rounded-t-lg"
|
||||||
:class="tab === t.id ? 'border-b-transparent border-[#ACC6E5] bg-white text-[var(--active-color)]':'border-transparent text-slate-500'"
|
:class="tab === t.id ? 'border-b-transparent border-[var(--border-color)] bg-white text-[var(--active-color)]':'border-transparent text-slate-500'"
|
||||||
:style="{'--active-color': themeStore.themeColor}"
|
:style="{
|
||||||
|
'--border-color': getColorWithOpacity(themeStore.themeColor, 0.3),
|
||||||
|
'--active-color': themeStore.themeColor
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<Icon :icon="t.icon" class="size-14px" />
|
<Icon :icon="t.icon" class="size-14px" />
|
||||||
{{ t.name }}
|
{{ t.name }}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ChangeStatus } from "../demo/model";
|
const props = defineProps<{ status: any }>();
|
||||||
const props = defineProps<{ status: ChangeStatus }>();
|
|
||||||
const BIG_STAGES = ["申请审批", "实施与关闭", "变更关闭"];
|
const BIG_STAGES = ["申请审批", "实施与关闭", "变更关闭"];
|
||||||
const bigStageOf = (s: ChangeStatus) => (s === "审批中" ? 0 : s === "已关闭" ? 2 : 1);
|
const bigStageOf = (s: any) => (s === "审批中" ? 0 : s === "已关闭" ? 2 : 1);
|
||||||
const cur = bigStageOf(props.status);
|
const cur = bigStageOf(props.status);
|
||||||
const pct = ((cur + 1) / BIG_STAGES.length) * 100;
|
const pct = ((cur + 1) / BIG_STAGES.length) * 100;
|
||||||
const size = 34, stroke = 4, r = (size - stroke) / 2, c = 2 * Math.PI * r;
|
const size = 34, stroke = 4, r = (size - stroke) / 2, c = 2 * Math.PI * r;
|
||||||
|
|||||||
@@ -2,32 +2,14 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import type { Component } from 'vue';
|
import type { Component } from 'vue';
|
||||||
import { getPaletteColorByNumber, mixColor } from '@sa/color';
|
import { getPaletteColorByNumber, mixColor } from '@sa/color';
|
||||||
import { loginModuleRecord } from '@/constants/app';
|
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
import PwdLogin from './modules/pwd-login.vue';
|
import PwdLogin from './modules/pwd-login.vue';
|
||||||
|
|
||||||
interface Props {
|
|
||||||
/** The login module */
|
|
||||||
module?: UnionKey.LoginModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
|
||||||
|
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const themeStore = useThemeStore();
|
const themeStore = useThemeStore();
|
||||||
|
|
||||||
interface LoginModule {
|
const activeModule = computed(() => ({ label: '密码登录', component: PwdLogin }));
|
||||||
label: App.I18n.I18nKey;
|
|
||||||
component: Component;
|
|
||||||
}
|
|
||||||
|
|
||||||
const moduleMap: Record<UnionKey.LoginModule, LoginModule> = {
|
|
||||||
'pwd-login': { label: loginModuleRecord['pwd-login'], component: PwdLogin },
|
|
||||||
};
|
|
||||||
|
|
||||||
const activeModule = computed(() => moduleMap[props.module || 'pwd-login']);
|
|
||||||
|
|
||||||
const bgThemeColor = computed(() =>
|
const bgThemeColor = computed(() =>
|
||||||
themeStore.darkMode ? getPaletteColorByNumber(themeStore.themeColor, 600) : themeStore.themeColor
|
themeStore.darkMode ? getPaletteColorByNumber(themeStore.themeColor, 600) : themeStore.themeColor
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
<script setup lang="ts"></script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<LookForward />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
Reference in New Issue
Block a user