Merge branch 'dev3' into dev2

This commit is contained in:
2025-03-04 16:53:41 +09:00
47 changed files with 314 additions and 277 deletions

View File

@@ -46,6 +46,9 @@ async def login(request: Request,db:Session= Depends(get_db) ,form_data: OAuth2P
data={"sub": user.id,"roles":roles,"permissions": permissions,"tenant":user.tenantid,}, data={"sub": user.id,"roles":roles,"permissions": permissions,"tenant":user.tenantid,},
expires_delta=access_token_expires, expires_delta=access_token_expires,
) )
request.state.user = user.id
return JSONResponse( return JSONResponse(
status_code=200, status_code=200,
content={"access_token": access_token, "token_type": "bearer","user_name":user.first_name + " " + user.last_name} content={"access_token": access_token, "token_type": "bearer","user_name":user.first_name + " " + user.last_name}

View File

@@ -9,7 +9,7 @@ from app.core import security
from app.db.cruddb import userService from app.db.cruddb import userService
from app.core.dbmanager import get_db from app.core.dbmanager import get_db
async def get_current_user(security_scopes: SecurityScopes, async def get_current_user(request: Request,security_scopes: SecurityScopes,
db=Depends(get_db), token: str = Depends(security.oauth2_scheme) db=Depends(get_db), token: str = Depends(security.oauth2_scheme)
): ):
credentials_exception = HTTPException( credentials_exception = HTTPException(
@@ -42,6 +42,7 @@ async def get_current_user(security_scopes: SecurityScopes,
user = userService.get_user(db, token_data.id) user = userService.get_user(db, token_data.id)
if user is None: if user is None:
raise credentials_exception raise credentials_exception
request.state.user = user.id
return user return user
async def get_current_active_user( async def get_current_active_user(

View File

@@ -1,8 +1,8 @@
import time import time
from typing import Any from typing import Any
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db.cruddb import domainService from app.db.cruddb import domainService,tenantService
from app.db.cruddb import tenantService from app.db.session import Database
class MemoryCache: class MemoryCache:
def __init__(self, max_cache_size: int = 100, ttl: int = 60): def __init__(self, max_cache_size: int = 100, ttl: int = 60):
@@ -60,12 +60,13 @@ class tenantCache:
def __init__(self): def __init__(self):
self.memoryCache = MemoryCache(max_cache_size=50, ttl=120) self.memoryCache = MemoryCache(max_cache_size=50, ttl=120)
def get_tenant_db(self,db: Session, tenantid: str): def get_tenant_db(self,db: Session, tenantid: str):
if not self.memoryCache.get(f"TENANT_{tenantid}"): if not self.memoryCache.get(f"TENANT_{tenantid}"):
tenant = tenantService.get_tenant(db,tenantid) tenant = tenantService.get_tenant(db,tenantid)
if tenant: if tenant:
self.memoryCache.set(f"TENANT_{tenantid}",tenant.db) database = Database(tenant.db)
return self.memoryCache.get(f"TENANT_{tenantid}") self.memoryCache.set(f"TENANT_{tenantid}",database)
return self.memoryCache.get(f"TENANT_{tenantid}")
tenantCacheService =tenantCache() tenantCacheService =tenantCache()

View File

@@ -1,13 +1,15 @@
from fastapi import Depends from fastapi import Depends,Request
from app.db.session import get_tenant_db,get_user_db from app.db.session import get_tenant_db
from app.core import tenantCacheService from app.core import tenantCacheService
from app.db.session import tenantdb from app.db.session import tenantdb
def get_db(tenant:str = "1",tenantdb = Depends(get_tenant_db)): def get_db(request: Request,tenant:str = "1",tenantdb = Depends(get_tenant_db)):
db_url = tenantCacheService.get_tenant_db(tenantdb,tenant) database = tenantCacheService.get_tenant_db(tenantdb,tenant)
db = get_user_db(db_url)
try: try:
db = database.get_db()
request.state.tenant = tenant
request.state.db = db
yield db yield db
finally: finally:
db.close() db.close()

View File

@@ -1,52 +1,75 @@
from fastapi import Request from fastapi import Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware from starlette.middleware.base import BaseHTTPMiddleware
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from app.db.models import OperationLog,User from app.db.models import OperationLog,User
from app.core.apiexception import APIException
from app.core.dbmanager import get_log_db
from app.db.crud import create_log
import json
from functools import wraps class LoggingMiddleware(BaseHTTPMiddleware):
from fastapi import Request async def dispatch(self, request: Request, call_next):
if request.method in ("POST", "PUT", "PATCH","DELETE"):
try:
request.state.body = await request.json()
except json.JSONDecodeError:
request.state.body = await request.body()
else:
request.state.body = None
def log_operation(func):
"""自定义装饰器用于记录操作日志"""
@wraps(func)
async def wrapper(*args, **kwargs):
if 'request' in kwargs and isinstance(kwargs['request'], Request):
request: Request = kwargs['request']
method = request.method
url = str(request.url)
client_ip = request.client.host
headers = dict(request.headers)
user_agent = headers.get("user-agent", "")
if 'db' in kwargs and isinstance(kwargs['db'], Session):
db = kwargs['db']
if 'user' in kwargs and isinstance(kwargs['user'], User):
user = kwargs['user']
user_id = user.id
tenant_id = user.tenantid
else:
user_id = None
tenant_id = None
try: try:
response = await func(*args, **kwargs) response = await call_next(request)
if db: state = request.state
db_operation = OperationLog(tenantid =tenant_id,
clientip =client_ip,
useragent =user_agent,
userid = user_id,
operation = method,
function = url,
response = f"status_code:{response.status_code }" )
db.add(db_operation)
db.commit()
except Exception as e: except Exception as e:
raise e await self.log_error(request, e)
return response response = JSONResponse(
return wrapper content={"detail": "Internal Server Error"},
status_code=500
)
if hasattr(request.state, "user") and hasattr(request.state, "tenant"):
await self.log_request(request, response,state)
return response
async def log_request(self, request: Request, response,state):
try:
headers = dict(request.headers)
route = request.scope.get("route")
if route:
path_template = route.path
else:
path_template = request.url.path
db_operation = OperationLog(tenantid =request.state.tenant,
clientip = request.client.host if request.client else None,
useragent =headers.get("user-agent", ""),
userid = request.state.user,
operation = request.method,
function = path_template,
parameters = str({"path": request.path_params,"query": dict(request.query_params),"body": request.state.body}),
response = f"status_code:{response.status_code }" )
db = request.state.db
if db:
await self.write_log_to_db(db_operation,db)
except Exception as e:
print(f"Logging failed: {str(e)}")
async def log_error(self, request: Request, e: Exception):
exc = APIException('operation:dispatch',request.url._url,f"Error occurred while writting operation log:",e)
db = get_log_db()
try:
create_log(db,exc.error)
finally:
db.close()
async def write_log_to_db(self, db_operation,db):
db.add(db_operation)
db.commit()

View File

@@ -1,14 +1,14 @@
from sqlalchemy import Boolean, Column, Integer, String, DateTime,ForeignKey,Table from sqlalchemy import Boolean, Column, Integer, String, DateTime,ForeignKey,Table
from sqlalchemy.orm import Mapped,relationship,as_declarative,mapped_column from sqlalchemy.orm import Mapped,relationship,as_declarative,mapped_column
from datetime import datetime from datetime import datetime,timezone
from app.db import Base from app.db import Base
from app.core.security import chacha20Decrypt from app.core.security import chacha20Decrypt
@as_declarative() @as_declarative()
class Base: class Base:
id = Column(Integer, primary_key=True, index=True) id = Column(Integer, primary_key=True, index=True)
create_time = Column(DateTime, default=datetime.now) create_time = Column(DateTime, default=datetime.now(timezone.utc))
update_time = Column(DateTime, default=datetime.now, onupdate=datetime.now) update_time = Column(DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc))
userrole = Table( userrole = Table(
@@ -234,6 +234,7 @@ class OperationLog(Base):
userid = mapped_column(Integer,ForeignKey("user.id")) userid = mapped_column(Integer,ForeignKey("user.id"))
operation = mapped_column(String(200)) operation = mapped_column(String(200))
function = mapped_column(String(200)) function = mapped_column(String(200))
parameters = mapped_column(String(200))
response = mapped_column(String(200)) response = mapped_column(String(200))
user = relationship('User') user = relationship('User')

View File

@@ -20,7 +20,7 @@ from app.db.crud import create_log
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
import asyncio import asyncio
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from app.core.operation import LoggingMiddleware
#Base.metadata.create_all(bind=engine) #Base.metadata.create_all(bind=engine)
@@ -45,6 +45,8 @@ app.add_middleware(
allow_headers=["*"], allow_headers=["*"],
) )
app.add_middleware(LoggingMiddleware)
add_pagination(app) add_pagination(app)
# @app.middleware("http") # @app.middleware("http")

View File

@@ -105,7 +105,7 @@ module.exports = configure(function (/* ctx */) {
config: {}, config: {},
// iconSet: 'material-icons', // Quasar icon set // iconSet: 'material-icons', // Quasar icon set
// lang: 'en-US', // Quasar language pack lang: 'ja', // Quasar language pack
// For special cases outside of where the auto-import strategy can have an impact // For special cases outside of where the auto-import strategy can have an impact
// (like functional components as one of the examples), // (like functional components as one of the examples),

View File

@@ -4,14 +4,14 @@ import { Router } from 'vue-router';
import { App } from 'vue'; import { App } from 'vue';
export default boot(({ app, router }: { app: App<Element>; router: Router }) => { export default boot(({ app, router }: { app: App<Element>; router: Router }) => {
document.documentElement.lang="ja-JP"; document.documentElement.lang='ja-JP';
app.config.errorHandler = (err: any, instance: any, info: string) => { app.config.errorHandler = (err: any, instance: any, info: string) => {
if (err.response && err.response.status === 401) { if (err.response && err.response.status === 401) {
// 認証エラーの場合再ログインする // 認証エラーの場合再ログインする
console.error('(; ゚Д゚)/認証エラー(401)', err, info); console.error('(; ゚Д゚)/認証エラー(401)', err, info);
localStorage.removeItem('token'); localStorage.removeItem('token');
router.replace({ router.replace({
path:"/login", path:'/login',
query:{redirect:router.currentRoute.value.fullPath} query:{redirect:router.currentRoute.value.fullPath}
}); });
} else { } else {

View File

@@ -52,7 +52,7 @@ export default {
filter:String filter:String
}, },
emits:[ emits:[
"clearFilter" 'clearFilter'
], ],
setup(props,{emit}) { setup(props,{emit}) {
const isLoaded=ref(false); const isLoaded=ref(false);

View File

@@ -46,9 +46,9 @@ export default defineComponent({
const { app } = toRefs(props); const { app } = toRefs(props);
const authStore = useAuthStore(); const authStore = useAuthStore();
const appinfo = ref<AppInfo>({ const appinfo = ref<AppInfo>({
appId: "", appId: '',
name: "", name: '',
description: "" description: ''
}); });
const link= ref(`${authStore.currentDomain.kintoneUrl}/k/${app.value}`); const link= ref(`${authStore.currentDomain.kintoneUrl}/k/${app.value}`);
const getAppInfo = async (appId:string|undefined) => { const getAppInfo = async (appId:string|undefined) => {
@@ -56,7 +56,7 @@ export default defineComponent({
return; return;
} }
let result : any ={appId:"",name:""}; let result : any ={appId:'',name:''};
let retry =0; let retry =0;
while(retry<=3 && result && result.appId!==appId){ while(retry<=3 && result && result.appId!==appId){
await new Promise(resolve => setTimeout(resolve, 1000)); await new Promise(resolve => setTimeout(resolve, 1000));

View File

@@ -175,7 +175,7 @@ export default defineComponent({
if (flowStore.appInfo?.appId === selected.id) { if (flowStore.appInfo?.appId === selected.id) {
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
caption: "エラー", caption: 'エラー',
message: 'データソースを現在のアプリにすることはできません。' message: 'データソースを現在のアプリにすることはできません。'
}); });
} else if (selected.id !== data.value.sourceApp.id) { } else if (selected.id !== data.value.sourceApp.id) {
@@ -208,7 +208,7 @@ export default defineComponent({
if (isDuplicate) { if (isDuplicate) {
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
caption: "エラー", caption: 'エラー',
message: '重複したフィールドは選択できません' message: '重複したフィールドは選択できません'
}); });
} else { } else {

View File

@@ -42,9 +42,9 @@ import { useQuasar } from 'quasar';
} }
}, },
emits:[ emits:[
"closed", 'closed',
"update:conditionTree", 'update:conditionTree',
"update:show" 'update:show'
], ],
setup(props,context) { setup(props,context) {
const appDg = ref(); const appDg = ref();
@@ -58,11 +58,11 @@ import { useQuasar } from 'quasar';
// message: `条件式を設定してください。` // message: `条件式を設定してください。`
// }); // });
// } // }
context.emit("update:conditionTree",tree.value); context.emit('update:conditionTree',tree.value);
} }
showflg.value=false; showflg.value=false;
context.emit("update:show",false); context.emit('update:show',false);
context.emit("closed",val); context.emit('closed',val);
}; };
const showflg =ref(props.show); const showflg =ref(props.show);
//条件式をコピーする //条件式をコピーする

View File

@@ -217,7 +217,7 @@ export default defineComponent( {
const canMerge =(node:INode)=>{ const canMerge =(node:INode)=>{
const checkedIndexs:number[] = ticked.value; const checkedIndexs:number[] = ticked.value;
const findNode = checkedIndexs.find(index=>node.index===index); const findNode = checkedIndexs.find(index=>node.index===index);
console.log("findNode=>",findNode!==undefined,findNode); console.log('findNode=>',findNode!==undefined,findNode);
return findNode!==undefined; return findNode!==undefined;
} }
//グループ化解散 //グループ化解散

View File

@@ -1,98 +1,105 @@
<template> <template>
<div class="q-pa-md"> <div class="q-pa-md">
<q-uploader <q-uploader
style="max-width: 400px" style="max-width: 400px"
:url="uploadUrl" :url="uploadUrl"
:label="title" :label="title"
:headers="headers" :headers="headers"
accept=".xlsx" accept=".xlsx"
v-on:rejected="onRejected" v-on:rejected="onRejected"
v-on:uploaded="onUploadFinished" v-on:uploaded="onUploadFinished"
v-on:failed="onFailed" v-on:failed="onFailed"
field-name="files" field-name="files"
></q-uploader> ></q-uploader>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { createUploaderComponent, useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import { useAuthStore } from 'src/stores/useAuthStore'; import { useAuthStore } from 'src/stores/useAuthStore';
import { ref } from 'vue'; import { ref } from 'vue';
const $q=useQuasar();
const authStore = useAuthStore();
const emit =defineEmits(['uploaded']);
/**
* ファイルアップロードを拒否する時の処理
* @param rejectedEntries
*/
function onRejected (rejectedEntries:any) {
// Notify plugin needs to be installed
// https://quasar.dev/quasar-plugins/notify#Installation
$q.notify({
type: 'negative',
message: `Excelファイルを選択してください。`
})
}
/** const $q = useQuasar();
* ファイルアップロード成功時の処理 const authStore = useAuthStore();
*/ const emit = defineEmits(['uploaded']);
function onUploadFinished({xhr}:{xhr:XMLHttpRequest}){
let msg="ファイルのアップロードが完了しました。";
if(xhr && xhr.response){
msg=`${msg} (${xhr.responseText})`;
}
$q.notify({
type: 'positive',
caption:"通知",
message: msg
});
setTimeout(() => {
emit('uploaded',xhr.responseText);
}, 2000);
}
/** interface Props {
* 例外発生時、responseからエラー情報を取得する title?: string;
* @param xhr uploadUrl?: string;
*/ }
function getResponseError(xhr:XMLHttpRequest){
try{
const resp = JSON.parse(xhr.responseText);
return 'detail' in resp ? resp.detail:'';
}catch(err){
return xhr.responseText;
}
}
/** const headers = ref([
* { name: 'Authorization', value: 'Bearer ' + authStore.token },
* @param info ファイルアップロード失敗時の処理 ]);
*/
function onFailed({files,xhr}:{files: readonly any[],xhr:XMLHttpRequest}){
let msg ="ファイルアップロードが失敗しました。";
if(xhr && xhr.status){
const detail = getResponseError(xhr);
msg=`${msg} (${xhr.status }:${detail})`
}
$q.notify({
type:"negative",
message:msg
});
}
interface Props { const props = withDefaults(defineProps<Props>(), {
title: string; title: '設計書から導入する(Excel)',
uploadUrl:string; uploadUrl: `${process.env.KAB_BACKEND_URL}api/v1/createappfromexcel?format=1`,
} });
const headers = ref([{name:"Authorization",value:'Bearer ' + authStore.token}]); /**
const props = withDefaults(defineProps<Props>(), { * ファイルアップロードを拒否する時の処理
title:"設計書から導入する(Excel)", * @param rejectedEntries
uploadUrl: `${process.env.KAB_BACKEND_URL}api/v1/createappfromexcel?format=1` */
function onRejected(rejectedEntries: any) {
// Notify plugin needs to be installed
// https://quasar.dev/quasar-plugins/notify#Installation
$q.notify({
type: 'negative',
message: 'Excelファイルを選択してください。',
});
}
}); /**
* ファイルアップロード成功時の処理
*/
function onUploadFinished({ xhr }: { xhr: XMLHttpRequest }) {
let msg = 'ファイルのアップロードが完了しました。';
if (xhr && xhr.response) {
msg = `${msg} (${xhr.responseText})`;
}
$q.notify({
type: 'positive',
caption: '通知',
message: msg,
});
setTimeout(() => {
emit('uploaded', xhr.responseText);
}, 2000);
}
/**
* 例外発生時、responseからエラー情報を取得する
* @param xhr
*/
function getResponseError(xhr: XMLHttpRequest) {
try {
const resp = JSON.parse(xhr.responseText);
return 'detail' in resp ? resp.detail : '';
} catch (err) {
return xhr.responseText;
}
}
/**
*
* @param info ファイルアップロード失敗時の処理
*/
function onFailed({
files,
xhr,
}: {
files: readonly any[];
xhr: XMLHttpRequest;
}) {
let msg = 'ファイルアップロードが失敗しました。';
if (xhr && xhr.status) {
const detail = getResponseError(xhr);
msg = `${msg} (${xhr.status}:${detail})`;
}
$q.notify({
type: 'negative',
message: msg,
});
}
</script> </script>
<style lang="scss"> <style lang="scss"></style>
</style>

View File

@@ -42,7 +42,7 @@ export default {
onMounted(() => { onMounted(() => {
loading.value = true; loading.value = true;
api.get(`api/domains`).then(res =>{ api.get('api/domains').then(res =>{
res.data.data.forEach((data) => { res.data.data.forEach((data) => {
const item = { const item = {
id: data.id, id: data.id,

View File

@@ -73,14 +73,14 @@ export default {
if(!props.blackListLabel.find(blackListItem => blackListItem === fld.label)){ if(!props.blackListLabel.find(blackListItem => blackListItem === fld.label)){
if(props.fieldTypes.length===0 || props.fieldTypes.includes(fld.type)){ if(props.fieldTypes.length===0 || props.fieldTypes.includes(fld.type)){
rows.push({id:index, name: fld.label || fld.code, ...fld }); rows.push({id:index, name: fld.label || fld.code, ...fld });
}else if(props.fieldTypes.includes("lookup") && ("lookup" in fld)){ }else if(props.fieldTypes.includes('lookup') && ('lookup' in fld)){
rows.push({id:index, name: fld.label || fld.code, ...fld }); rows.push({id:index, name: fld.label || fld.code, ...fld });
} }
} }
} else { } else {
if(props.fieldTypes.length===0 || props.fieldTypes.includes(fld.type)){ if(props.fieldTypes.length===0 || props.fieldTypes.includes(fld.type)){
rows.push({id:index, name: fld.label || fld.code, ...fld }); rows.push({id:index, name: fld.label || fld.code, ...fld });
}else if(props.fieldTypes.includes("lookup") && ("lookup" in fld)){ }else if(props.fieldTypes.includes('lookup') && ('lookup' in fld)){
rows.push({id:index, name: fld.label || fld.code, ...fld }); rows.push({id:index, name: fld.label || fld.code, ...fld });
} }
} }

View File

@@ -242,7 +242,7 @@ function isManager(userId: number) {
const getUsers = async () => { const getUsers = async () => {
loading.value = true; loading.value = true;
const result = await api.get(`api/v1/users`); const result = await api.get('api/v1/users');
allUsers.value = result.data.data.map(itemToDisplay); allUsers.value = result.data.data.map(itemToDisplay);
loading.value = false; loading.value = false;
} }

View File

@@ -34,7 +34,7 @@ interface Props {
const props = defineProps<Props>(); const props = defineProps<Props>();
async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) { async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
return api.post(`api/managedomain`, { return api.post('api/managedomain', {
userid: user.id, userid: user.id,
domainid: domain.id, domainid: domain.id,
}); });

View File

@@ -29,7 +29,7 @@ interface Props {
const props = defineProps<Props>(); const props = defineProps<Props>();
async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) { async function shareApi(user: IUserDisplay, domain: IDomainOwnerDisplay) {
return api.post(`api/userdomain`, { return api.post('api/userdomain', {
userid: user.id, userid: user.id,
domainid: domain.id, domainid: domain.id,
}); });

View File

@@ -23,7 +23,7 @@ defineExpose({
}) })
const getUsers = async (filter = () => true) => { const getUsers = async (filter = () => true) => {
loading.value = true; loading.value = true;
const result = await api.get(`api/v1/users`); const result = await api.get('api/v1/users');
rows.value = result.data.data.map((item) => { rows.value = result.data.data.map((item) => {
return { id: item.id, firstName: item.first_name, lastName: item.last_name, email: item.email, isSuperuser: item.is_superuser, isActive: item.is_active } return { id: item.id, firstName: item.first_name, lastName: item.last_name, email: item.email, isSuperuser: item.is_superuser, isActive: item.is_active }
}).filter(filter); }).filter(filter);

View File

@@ -55,7 +55,7 @@ export default {
]; ];
const fetchUsers = async () => { const fetchUsers = async () => {
const result = await api.get(`api/v1/users`); const result = await api.get('api/v1/users');
return result.data.data.map((item: any) => { return result.data.data.map((item: any) => {
return { id: item.id, firstName: item.first_name, lastName: item.last_name, email: item.email, isSuperuser: item.is_superuser, isActive: item.is_active, roles: item.roles.map(role => role.id) } return { id: item.id, firstName: item.first_name, lastName: item.last_name, email: item.email, isSuperuser: item.is_superuser, isActive: item.is_active, roles: item.roles.map(role => role.id) }
}).filter(user => !props.filterInitRowsFunc || props.filterInitRowsFunc(user)); }).filter(user => !props.filterInitRowsFunc || props.filterInitRowsFunc(user));

View File

@@ -44,7 +44,7 @@ import { useAuthStore } from 'src/stores/useAuthStore';
export default defineComponent({ export default defineComponent({
name: 'AppSelector', name: 'AppSelector',
emits:[ emits:[
"appSelected" 'appSelected'
], ],
components:{ components:{
AppSelectBox, AppSelectBox,
@@ -59,7 +59,7 @@ export default defineComponent({
const closeDg=(val :any)=>{ const closeDg=(val :any)=>{
showSelectApp.value=false; showSelectApp.value=false;
console.log("Dialog closed->",val); console.log('Dialog closed->',val);
if (val == 'OK') { if (val == 'OK') {
const data = appDg.value.selected[0]; const data = appDg.value.selected[0];
console.log(data); console.log(data);

View File

@@ -74,7 +74,7 @@ export default defineComponent({
const selectedEvent = ref<IKintoneEvent | undefined>(store.selectedEvent); const selectedEvent = ref<IKintoneEvent | undefined>(store.selectedEvent);
const selectedChangeEvent = ref<IKintoneEventGroup | undefined>(undefined); const selectedChangeEvent = ref<IKintoneEventGroup | undefined>(undefined);
const isFieldChange = (node: IKintoneEventNode) => { const isFieldChange = (node: IKintoneEventNode) => {
return node.header == 'EVENT' && node.eventId.indexOf(".change.") > -1; return node.header == 'EVENT' && node.eventId.indexOf('.change.') > -1;
} }
const getSelectedClass = (node: IKintoneEventNode) => { const getSelectedClass = (node: IKintoneEventNode) => {
@@ -117,7 +117,7 @@ export default defineComponent({
$q.notify({ $q.notify({
type: 'positive', type: 'positive',
caption: "通知", caption: '通知',
message: `イベント ${node.label} 削除` message: `イベント ${node.label} 削除`
}) })
} }

View File

@@ -92,11 +92,11 @@ export default defineComponent({
}, },
emits: [ emits: [
'addNode', 'addNode',
"nodeSelected", 'nodeSelected',
"nodeEdit", 'nodeEdit',
"deleteNode", 'deleteNode',
"deleteAllNextNodes", 'deleteAllNextNodes',
"copyFlow" 'copyFlow'
], ],
setup(props, context) { setup(props, context) {
const store = useFlowEditorStore(); const store = useFlowEditorStore();
@@ -204,7 +204,7 @@ export default defineComponent({
* 変数名取得 * 変数名取得
*/ */
const varName =(node:IActionNode)=>{ const varName =(node:IActionNode)=>{
const prop = node.actionProps.find((prop) => prop.props.name === "verName"); const prop = node.actionProps.find((prop) => prop.props.name === 'verName');
return prop?.props.modelValue.name; return prop?.props.modelValue.name;
}; };
const copyFlow=()=>{ const copyFlow=()=>{

View File

@@ -31,11 +31,11 @@
import { ref, defineComponent, computed, PropType } from 'vue'; import { ref, defineComponent, computed, PropType } from 'vue';
import { IActionNode, ActionNode, ActionFlow, RootAction } from '../../types/ActionTypes'; import { IActionNode, ActionNode, ActionFlow, RootAction } from '../../types/ActionTypes';
export enum Direction { export enum Direction {
Default = "None", Default = 'None',
Left = "LEFT", Left = 'LEFT',
Right = "RIGHT", Right = 'RIGHT',
LeftNotNext = "LEFTNOTNEXT", LeftNotNext = 'LEFTNOTNEXT',
RightNotNext = "RIGHTNOTNEXT", RightNotNext = 'RIGHTNOTNEXT',
} }
export default defineComponent({ export default defineComponent({
name: 'NodeLine', name: 'NodeLine',

View File

@@ -55,7 +55,7 @@ export default defineComponent({
}); });
const connectProps=(props:IProp)=>{ const connectProps=(props:IProp)=>{
const connProps:any={}; const connProps:any={};
if(props && "connectProps" in props && props.connectProps!=undefined){ if(props && 'connectProps' in props && props.connectProps!=undefined){
for(let connProp of props.connectProps){ for(let connProp of props.connectProps){
let targetProp = componentData.value.find((prop)=>prop.props.name===connProp.propName); let targetProp = componentData.value.find((prop)=>prop.props.name===connProp.propName);
if(targetProp){ if(targetProp){

View File

@@ -72,11 +72,11 @@ export default defineComponent({
} }
}, },
setup(props, { emit }) { setup(props, { emit }) {
const color = ref(props.modelValue??""); const color = ref(props.modelValue??'');
const isSelected = computed(()=>props.modelValue && props.modelValue!==""); const isSelected = computed(()=>props.modelValue && props.modelValue!=='');
const customExp = props.rules === undefined ? [] : eval(props.rules); const customExp = props.rules === undefined ? [] : eval(props.rules);
const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}が必須です。`; const errmsg = props.requiredMessage?props.requiredMessage:`${props.displayName}が必須です。`;
const requiredExp = props.required?[((val:any)=>!!val || errmsg ),"anyColor"]:[]; const requiredExp = props.required?[((val:any)=>!!val || errmsg ),'anyColor']:[];
const rulesExp=[...requiredExp,...customExp]; const rulesExp=[...requiredExp,...customExp];
watchEffect(()=>{ watchEffect(()=>{
emit('update:modelValue', color.value); emit('update:modelValue', color.value);

View File

@@ -91,7 +91,7 @@ export default defineComponent({
}, },
setup(props, { emit }) { setup(props, { emit }) {
let source = reactive(props.connectProps["source"]); let source = reactive(props.connectProps['source']);
if(!source){ if(!source){
source = props.context.find(element => element.props.name === 'sources'); source = props.context.find(element => element.props.name === 'sources');
} }

View File

@@ -206,32 +206,32 @@ export default defineComponent({
//集計処理方法 //集計処理方法
const logicalOperators = ref([ const logicalOperators = ref([
{ {
"operator": "", 'operator': '',
"label": "なし" 'label': 'なし'
}, },
{ {
"operator": "SUM", 'operator': 'SUM',
"label": "合計" 'label': '合計'
}, },
{ {
"operator": "AVG", 'operator': 'AVG',
"label": "平均" 'label': '平均'
}, },
{ {
"operator": "MAX", 'operator': 'MAX',
"label": "最大値" 'label': '最大値'
}, },
{ {
"operator": "MIN", 'operator': 'MIN',
"label": "最小値" 'label': '最小値'
}, },
{ {
"operator": "COUNT", 'operator': 'COUNT',
"label": "カウント" 'label': 'カウント'
}, },
{ {
"operator": "FIRST", 'operator': 'FIRST',
"label": "最初の値" 'label': '最初の値'
} }
]); ]);
const checkInput=(val:ValueType)=>{ const checkInput=(val:ValueType)=>{
@@ -239,13 +239,13 @@ export default defineComponent({
return false; return false;
} }
if(!val.name){ if(!val.name){
return "集計結果の変数名を入力してください"; return '集計結果の変数名を入力してください';
} }
if(!val.vars || val.vars.length==0){ if(!val.vars || val.vars.length==0){
return "集計処理を設定してください"; return '集計処理を設定してください';
} }
if(val.vars.some((x)=>!x.vName)){ if(val.vars.some((x)=>!x.vName)){
return "集計結果変数名を入力してください"; return '集計結果変数名を入力してください';
} }
return true; return true;
} }

View File

@@ -70,14 +70,14 @@ export default defineComponent({
const eventId =store.currentFlow?.getRoot()?.name; const eventId =store.currentFlow?.getRoot()?.name;
if(eventId===undefined){return;} if(eventId===undefined){return;}
let displayName = inputValue.value; let displayName = inputValue.value;
if(props.connectProps!==undefined && "displayName" in props.connectProps){ if(props.connectProps!==undefined && 'displayName' in props.connectProps){
displayName =props.connectProps["displayName"].props.modelValue; displayName =props.connectProps['displayName'].props.modelValue;
} }
const customButtonId=`${eventId}.customButtonClick`; const customButtonId=`${eventId}.customButtonClick`;
const findedEvent = store.eventTree.findEventById(customButtonId); const findedEvent = store.eventTree.findEventById(customButtonId);
if(findedEvent && "events" in findedEvent){ if(findedEvent && 'events' in findedEvent){
const customEvents = findedEvent as IKintoneEventGroup; const customEvents = findedEvent as IKintoneEventGroup;
const addEventId = customButtonId+"." + inputValue.value; const addEventId = customButtonId+'.' + inputValue.value;
if(store.eventTree.findEventById(addEventId)){ if(store.eventTree.findEventById(addEventId)){
return; return;
} }

View File

@@ -71,7 +71,7 @@ export default defineComponent({
const rulesExp=[...requiredExp,...customExp]; const rulesExp=[...requiredExp,...customExp];
watchEffect(()=>{ watchEffect(()=>{
emit("update:modelValue",numValue.value); emit('update:modelValue',numValue.value);
}); });
return { return {
numValue, numValue,

View File

@@ -59,7 +59,7 @@ export default defineComponent({
const properties=ref(props.nodeProps); const properties=ref(props.nodeProps);
const connectProps=(props:IProp)=>{ const connectProps=(props:IProp)=>{
const connProps:any={context:properties}; const connProps:any={context:properties};
if(props && "connectProps" in props && props.connectProps!=undefined){ if(props && 'connectProps' in props && props.connectProps!=undefined){
for(let connProp of props.connectProps){ for(let connProp of props.connectProps){
let targetProp = properties.value.find((prop)=>prop.props.name===connProp.propName); let targetProp = properties.value.find((prop)=>prop.props.name===connProp.propName);
if(targetProp){ if(targetProp){

View File

@@ -9,7 +9,7 @@ export class Auth
params.append('username', user); params.append('username', user);
params.append('password', pwd); params.append('password', pwd);
try{ try{
const result = await api.post(`api/token`,params); const result = await api.post('api/token',params);
console.info(result); console.info(result);
localStorage.setItem('Token', result.data.access_token); localStorage.setItem('Token', result.data.access_token);
return true; return true;

View File

@@ -130,15 +130,15 @@ const route = useRoute()
const appDg = ref(); const appDg = ref();
const prevNodeIfo = ref({ const prevNodeIfo = ref({
prevNode: {} as IActionNode, prevNode: {} as IActionNode,
inputPoint: "" inputPoint: ''
}); });
// const refFlow = ref<ActionFlow|null>(null); // const refFlow = ref<ActionFlow|null>(null);
const showAddAction = ref(false); const showAddAction = ref(false);
const saveVersionAction = ref(false); const saveVersionAction = ref(false);
const versionInputRef = ref(); const versionInputRef = ref();
const drawerRight = ref(false); const drawerRight = ref(false);
const filter=ref(""); const filter=ref('');
const model = ref(""); const model = ref('');
const rootNode = computed(()=>{ const rootNode = computed(()=>{
return store.currentFlow?.getRoot(); return store.currentFlow?.getRoot();
@@ -148,11 +148,11 @@ const minPanelWidth=computed(()=>{
if(store.currentFlow && root){ if(store.currentFlow && root){
return store.currentFlow?.getColumns(root) * 300 + 'px'; return store.currentFlow?.getColumns(root) * 300 + 'px';
}else{ }else{
return "300px"; return '300px';
} }
}); });
const fixedLeftPosition = computed(()=>{ const fixedLeftPosition = computed(()=>{
return drawerLeft.value?"300px":"0px"; return drawerLeft.value?'300px':'0px';
}); });
const addNode = (node: IActionNode, inputPoint: string) => { const addNode = (node: IActionNode, inputPoint: string) => {
@@ -195,12 +195,12 @@ const onDeleteAllNextNodes = (node: IActionNode) => {
store.currentFlow?.removeAllNext(node.id); store.currentFlow?.removeAllNext(node.id);
} }
const closeDg = (val: any) => { const closeDg = (val: any) => {
console.log("Dialog closed->", val); console.log('Dialog closed->', val);
if (val == 'OK' && appDg?.value?.selected?.length > 0) { if (val == 'OK' && appDg?.value?.selected?.length > 0) {
const data = appDg.value.selected[0]; const data = appDg.value.selected[0];
const actionProps = JSON.parse(data.property); const actionProps = JSON.parse(data.property);
const outputPoint = JSON.parse(data.outputPoints); const outputPoint = JSON.parse(data.outputPoints);
const action = new ActionNode(data.name, data.desc, "", outputPoint, actionProps); const action = new ActionNode(data.name, data.desc, '', outputPoint, actionProps);
store.currentFlow?.addNode(action, prevNodeIfo.value.prevNode, prevNodeIfo.value.inputPoint); store.currentFlow?.addNode(action, prevNodeIfo.value.prevNode, prevNodeIfo.value.inputPoint);
} }
} }
@@ -227,8 +227,8 @@ const onDeploy = async () => {
if (store.appInfo === undefined || store.flows?.length === 0) { if (store.appInfo === undefined || store.flows?.length === 0) {
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
caption: "エラー", caption: 'エラー',
message: `設定されたフローがありません。` message: '設定されたフローがありません。'
}); });
return; return;
} }
@@ -238,16 +238,16 @@ const onDeploy = async () => {
deployLoading.value = false; deployLoading.value = false;
$q.notify({ $q.notify({
type: 'positive', type: 'positive',
caption: "通知", caption: '通知',
message: `デプロイを成功しました。` message: 'デプロイを成功しました。'
}); });
} catch (error) { } catch (error) {
console.error(error); console.error(error);
deployLoading.value = false; deployLoading.value = false;
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
caption: "エラー", caption: 'エラー',
message: `デプロイが失敗しました。` message: 'デプロイが失敗しました。'
}) })
} }
return; return;
@@ -258,7 +258,7 @@ const onSaveActionProps=(props:IActionProperty[])=>{
store.activeNode.actionProps=props; store.activeNode.actionProps=props;
$q.notify({ $q.notify({
type: 'positive', type: 'positive',
caption: "通知", caption: '通知',
message: `${store.activeNode?.subTitle}の属性を設定しました。(保存はされていません)` message: `${store.activeNode?.subTitle}の属性を設定しました。(保存はされていません)`
}); });
} }
@@ -291,7 +291,7 @@ const onSaveFlow = async () => {
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
caption: 'エラー', caption: 'エラー',
message: `選択中のフローがありません。` message: '選択中のフローがありません。'
}); });
return; return;
} }
@@ -301,7 +301,7 @@ const onSaveFlow = async () => {
saveLoading.value = false; saveLoading.value = false;
$q.notify({ $q.notify({
type: 'positive', type: 'positive',
caption: "通知", caption: '通知',
message: `${targetFlow.getRoot()?.subTitle}のフロー設定を保存しました。` message: `${targetFlow.getRoot()?.subTitle}のフロー設定を保存しました。`
}); });
} catch (error) { } catch (error) {
@@ -309,7 +309,7 @@ const onSaveFlow = async () => {
saveLoading.value = false; saveLoading.value = false;
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
caption: "エラー", caption: 'エラー',
message: `${targetFlow.getRoot()?.subTitle}のフローの設定の保存が失敗しました。` message: `${targetFlow.getRoot()?.subTitle}のフローの設定の保存が失敗しました。`
}) })
} }
@@ -324,7 +324,7 @@ const onSaveAllFlow= async ()=>{
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
caption: 'エラー', caption: 'エラー',
message: `設定されたフローがありません。` message: '設定されたフローがありません。'
}); });
return; return;
} }
@@ -338,8 +338,8 @@ const onSaveAllFlow= async ()=>{
} }
$q.notify({ $q.notify({
type: 'positive', type: 'positive',
caption: "通知", caption: '通知',
message: `すべてのフロー設定を保存しました。` message: 'すべてのフロー設定を保存しました。'
}); });
saveLoading.value = false; saveLoading.value = false;
}catch (error) { }catch (error) {
@@ -347,8 +347,8 @@ const onSaveAllFlow= async ()=>{
saveLoading.value = false; saveLoading.value = false;
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
caption: "エラー", caption: 'エラー',
message: `フローの設定の保存が失敗しました。` message: 'フローの設定の保存が失敗しました。'
}); });
} }
} }

View File

@@ -27,23 +27,23 @@ import ActionSelect from 'components/ActionSelect.vue';
import PropertyPanel from 'components/right/PropertyPanel.vue'; import PropertyPanel from 'components/right/PropertyPanel.vue';
const rootNode:RootAction =new RootAction("app.record.create.submit","レコード追加画面","保存するとき"); const rootNode:RootAction =new RootAction('app.record.create.submit','レコード追加画面','保存するとき');
const actionFlow: ActionFlow = new ActionFlow(rootNode); const actionFlow: ActionFlow = new ActionFlow(rootNode);
const saibanProps:IActionProperty[]=[{ const saibanProps:IActionProperty[]=[{
component:"InputText", component:'InputText',
props:{ props:{
displayName:"フォーマット", displayName:'フォーマット',
modelValue:"", modelValue:'',
name:"format", name:'format',
placeholder:"フォーマットを入力してください", placeholder:'フォーマットを入力してください',
} }
},{ },{
component:"FieldInput", component:'FieldInput',
props:{ props:{
displayName:"採番項目", displayName:'採番項目',
modelValue:"", modelValue:'',
name:"field", name:'field',
placeholder:"採番項目を選択してください", placeholder:'採番項目を選択してください',
} }
}]; }];
@@ -91,7 +91,7 @@ const onDeleteAllNextNodes=(node:IActionNode)=>{
refFlow.value.removeAllNext(node.id); refFlow.value.removeAllNext(node.id);
} }
const closeDg=(val :any)=>{ const closeDg=(val :any)=>{
console.log("Dialog closed->",val); console.log('Dialog closed->',val);
} }
</script> </script>

View File

@@ -1,12 +1,11 @@
<template> <template>
<q-page> <q-page>
<div class="q-pa-md"> <div class="q-pa-md">
<div class="q-gutter-sm row items-start"> <div class="q-gutter-sm row items-start">
<q-breadcrumbs> <q-breadcrumbs>
<q-breadcrumbs-el icon="home" label="ホーム" /> <q-breadcrumbs-el icon="home" label="ホーム" />
</q-breadcrumbs> </q-breadcrumbs>
</div> </div>
<div class="q-gutter-sm row items-start"> <div class="q-gutter-sm row items-start">
<doc-uploader @uploaded="onAppUploaded"></doc-uploader> <doc-uploader @uploaded="onAppUploaded"></doc-uploader>
</div> </div>
@@ -16,28 +15,26 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ref} from 'vue' import { ref } from 'vue';
import DocUploader from 'components/DocUpload.vue'; import DocUploader from 'components/DocUpload.vue';
import AppInfo from 'components/AppInfo.vue'; import AppInfo from 'components/AppInfo.vue';
import { AppSeed } from 'src/components/models'; import { AppSeed } from 'src/components/models';
interface AppInfo { interface AppInfo {
app:string, app: string;
revision:string revision: string;
} }
const appseed = withDefaults( defineProps<AppSeed>(),{ const appseed = withDefaults(defineProps<AppSeed>(), {
app:'' app: '',
}); });
// const appseed = defineProps<AppSeed>(); // const appseed = defineProps<AppSeed>();
const props = ref(appseed); const props = ref(appseed);
function onAppUploaded(responseText :string){ function onAppUploaded(responseText: string) {
let json:AppInfo = JSON.parse(responseText); let json: AppInfo = JSON.parse(responseText);
props.value=json; props.value = json;
} }
</script> </script>

View File

@@ -61,7 +61,7 @@ import { useAuthStore } from 'stores/useAuthStore';
let email = ref(''); let email = ref('');
let password = ref(''); let password = ref('');
let visibility = ref(false); let visibility = ref(false);
let passwordFieldType = ref('password'); let passwordFieldType = ref<'text'|'password'>('password');
let visibilityIcon = ref('visibility'); let visibilityIcon = ref('visibility');
const required = (val:string) => { const required = (val:string) => {
return (val && val.length > 0 || '必須項目') return (val && val.length > 0 || '必須項目')

View File

@@ -66,8 +66,8 @@ interface Props {
actions: string[]; actions: string[];
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
title: "ルールエディター", title: 'ルールエディター',
actions: () => ["フィールド制御", "一覧画面", "その他"] actions: () => ['フィールド制御', '一覧画面', 'その他']
}); });
function onItemClick(evt: Event) { function onItemClick(evt: Event) {
return; return;

View File

@@ -250,7 +250,7 @@ const isOwner = (row: IDomainOwnerDisplay) => row.owner.id === Number(authStore.
const getDomain = async (filter?: (row: IDomainOwnerDisplay) => boolean) => { const getDomain = async (filter?: (row: IDomainOwnerDisplay) => boolean) => {
loading.value = true; loading.value = true;
const { data } = await api.get<{data:IDomain[]}>(`api/domains`); const { data } = await api.get<{data:IDomain[]}>('api/domains');
rows.value = data.data.map((item) => { rows.value = data.data.map((item) => {
return { return {
id: item.id, id: item.id,
@@ -309,7 +309,7 @@ const deleteDomain = () => {
editId.value = 0; // set in removeRow() editId.value = 0; // set in removeRow()
}; };
function editRow(row) { function editRow(row: any) {
isCreate.value = false isCreate.value = false
editId.value = row.id; editId.value = row.id;
// tenantid.value = row.tenantid; // tenantid.value = row.tenantid;
@@ -350,7 +350,7 @@ const onSubmit = () => {
'ownerid': authStore.userId || '' 'ownerid': authStore.userId || ''
} }
// for search: api.put(`api/domain`)、api.post(`api/domain`) // for search: api.put(`api/domain`)、api.post(`api/domain`)
api[method].apply(api, [`api/domain`, param]).then(async (resp: any) => { api[method].apply(api, ['api/domain', param]).then(async (resp: any) => {
const res = resp.data; const res = resp.data;
if (res.data.id === currentDomainId.value && !res.data.is_active) { if (res.data.id === currentDomainId.value && !res.data.is_active) {
await authStore.setCurrentDomain(); await authStore.setCurrentDomain();

View File

@@ -14,7 +14,7 @@
<q-btn class="q-mx-none" color="primary" label="追加" @click="clickAddDomain()" /> <q-btn class="q-mx-none" color="primary" label="追加" @click="clickAddDomain()" />
<q-space /> <q-space />
<div class="row q-gutter-md"> <div class="row q-gutter-md">
<q-input borderless dense filled debounce="300" v-model="userDomainTableFilter" placeholder="Search"> <q-input borderless dense filled debounce="300" v-model="userDomainTableFilter" placeholder="検索">
<template v-slot:append> <template v-slot:append>
<q-icon name="search" /> <q-icon name="search" />
</template> </template>
@@ -114,7 +114,7 @@ const addUserDomainFinished = async (val: string) => {
const selected = addDomainRef.value.selected; const selected = addDomainRef.value.selected;
if (val == 'OK' && selected.length > 0) { if (val == 'OK' && selected.length > 0) {
addUserDomainLoading.value = true; addUserDomainLoading.value = true;
const { data } = await api.post(`api/userdomain`, { const { data } = await api.post('api/userdomain', {
userid: authStore.userId, userid: authStore.userId,
domainid: selected[0].id, domainid: selected[0].id,
}); });
@@ -169,9 +169,9 @@ const isActive = computed(() => (id: number) => {
const getDomain = async (userId? : string) => { const getDomain = async (userId? : string) => {
rowIds.clear(); rowIds.clear();
const resp = await api.get(`api/defaultdomain`); const resp = await api.get('api/defaultdomain');
activeDomainId.value = resp?.data?.data?.id; activeDomainId.value = resp?.data?.data?.id;
const domainResult = userId ? await api.get(`api/domain?userId=${userId}`) : await api.get(`api/domain`); const domainResult = userId ? await api.get(`api/domain?userId=${userId}`) : await api.get('api/domain');
const domains = domainResult.data as any[]; const domains = domainResult.data as any[];
rows.value = domains.sort((a, b) => a.id - b.id).reduce((acc, item) => { rows.value = domains.sort((a, b) => a.id - b.id).reduce((acc, item) => {
rowIds.add(item.id); rowIds.add(item.id);

View File

@@ -54,8 +54,8 @@ const mouseenter = (event: Event) => {
let oDivs = oDiv1?.getElementsByClassName('add'); let oDivs = oDiv1?.getElementsByClassName('add');
if (oDivs.length === 0) { if (oDivs.length === 0) {
let oDiv2 = document.createElement('div'); let oDiv2 = document.createElement('div');
oDiv2.className = "add"; oDiv2.className = 'add';
oDiv2.setAttribute("style", "display:table-row;height:inherit;position: absolute;left:calc(50% - 19px);"); oDiv2.setAttribute('style', 'display:table-row;height:inherit;position: absolute;left:calc(50% - 19px);');
oDiv2.innerHTML = oAdd; oDiv2.innerHTML = oAdd;
oDiv1?.append(oDiv2); oDiv1?.append(oDiv2);
} }

View File

@@ -16,7 +16,7 @@ const routes: RouteRecordRaw[] = [
path: '/', path: '/',
component: () => import('layouts/MainLayout.vue'), component: () => import('layouts/MainLayout.vue'),
children: [ children: [
{ path: '', component: () => import('pages/IndexPage.vue') }, { path: '', component: () => import('pages/IndexPage.vue'), props: { app: '' } },
{ path: 'ruleEditor', component: () => import('pages/RuleEditor.vue') }, { path: 'ruleEditor', component: () => import('pages/RuleEditor.vue') },
{ path: 'flow', component: () => import('pages/testFlow.vue') }, { path: 'flow', component: () => import('pages/testFlow.vue') },
{ path: 'FlowChartTest', component: () => import('pages/FlowChartTest.vue') }, { path: 'FlowChartTest', component: () => import('pages/FlowChartTest.vue') },

View File

@@ -103,5 +103,5 @@ function appToAppDisplay(app: IManagedApp) {
} }
function formatDate(data: string) { function formatDate(data: string) {
return date.formatDate(data, 'YYYY/MM/DD HH:mm'); return date.formatDate(new Date(data + 'Z'), 'YYYY/MM/DD HH:mm');
} }

View File

@@ -64,7 +64,7 @@ export const useAuthStore = defineStore('auth', {
params.append('username', username); params.append('username', username);
params.append('password', password); params.append('password', password);
try { try {
const result = await api.post(`api/token`, params); const result = await api.post('api/token', params);
// console.info(result); // console.info(result);
this.token = result.data.access_token; this.token = result.data.access_token;
const tokenJson = jwtDecode<{sub: number, tenant: string, roles: string}>(result.data.access_token); const tokenJson = jwtDecode<{sub: number, tenant: string, roles: string}>(result.data.access_token);
@@ -86,7 +86,7 @@ export const useAuthStore = defineStore('auth', {
} }
}, },
async loadCurrentDomain() { async loadCurrentDomain() {
const resp = await api.get<IResponse<IDomain>>(`api/defaultdomain`); const resp = await api.get<IResponse<IDomain>>('api/defaultdomain');
const activedomain = resp?.data?.data; const activedomain = resp?.data?.data;
if (!activedomain) { if (!activedomain) {
this.currentDomain = {} as IDomainInfo; this.currentDomain = {} as IDomainInfo;
@@ -99,13 +99,13 @@ export const useAuthStore = defineStore('auth', {
} }
}, },
async loadUserInfo() { async loadUserInfo() {
const resp = (await api.get<IResponse<IUser>>(`api/v1/users/me`))?.data?.data; const resp = (await api.get<IResponse<IUser>>('api/v1/users/me'))?.data?.data;
this.userInfo = userToUserRolesDisplay(resp) this.userInfo = userToUserRolesDisplay(resp)
}, },
async loadPermission() { async loadPermission() {
this.permissions = {} as IPermissions; this.permissions = {} as IPermissions;
if (this.isSuperAdmin) return; if (this.isSuperAdmin) return;
const resp = (await api.get<IResponse<IPermission[]>>(`api/v1/userpermssions`)).data.data; const resp = (await api.get<IResponse<IPermission[]>>('api/v1/userpermssions')).data.data;
resp.forEach((permission) => { resp.forEach((permission) => {
this.permissions[permission.link] = permission.menu; this.permissions[permission.link] = permission.menu;
this.permissions[permission.privilege] = permission.function; this.permissions[permission.privilege] = permission.function;

View File

@@ -129,7 +129,7 @@ export class ActionNode implements IActionNode {
id: string; id: string;
name: string; name: string;
get title(): string { get title(): string {
const prop = this.actionProps.find((prop) => prop.props.name === "displayName"); const prop = this.actionProps.find((prop) => prop.props.name === 'displayName');
return prop?.props.modelValue; return prop?.props.modelValue;
}; };
get subTitle(): string { get subTitle(): string {
@@ -138,7 +138,7 @@ export class ActionNode implements IActionNode {
//変数名 //変数名
get varName():IProp|undefined{ get varName():IProp|undefined{
const prop = this.actionProps.find((prop) => prop.props.name === "verName"); const prop = this.actionProps.find((prop) => prop.props.name === 'verName');
return prop?.props; return prop?.props;
} }

View File

@@ -136,7 +136,7 @@ export class KintoneEventManager {
const flows:IActionFlow[]=[]; const flows:IActionFlow[]=[];
for (const screen of this.screens) { for (const screen of this.screens) {
for (const event of screen.events) { for (const event of screen.events) {
if (event.header === "EVENT") { if (event.header === 'EVENT') {
const eventNode = event as IKintoneEvent; const eventNode = event as IKintoneEvent;
if(eventNode.flowData!==undefined){ if(eventNode.flowData!==undefined){
flows.push(eventNode.flowData); flows.push(eventNode.flowData);
@@ -144,7 +144,7 @@ export class KintoneEventManager {
}else if (event.header === 'EVENTGROUP' || event.header === 'CHANGE') { }else if (event.header === 'EVENTGROUP' || event.header === 'CHANGE') {
const eventGroup = event as IKintoneEventGroup; const eventGroup = event as IKintoneEventGroup;
eventGroup.events.forEach((ev) => { eventGroup.events.forEach((ev) => {
if (ev.header === "EVENT" || ev.header === "DELETABLE") { if (ev.header === 'EVENT' || ev.header === 'DELETABLE') {
const eventNode = ev as IKintoneEvent; const eventNode = ev as IKintoneEvent;
if(eventNode.flowData!==undefined){ if(eventNode.flowData!==undefined){
flows.push(eventNode.flowData); flows.push(eventNode.flowData);