bug修改

This commit is contained in:
闵炳辉 2024-06-28 14:38:12 +08:00
parent 6b14550f85
commit 6476418b5d
3 changed files with 159 additions and 171 deletions

View File

@ -94,8 +94,8 @@
</el-form-item> </el-form-item>
<el-form-item label="&nbsp;&nbsp;菜单权限:"> <el-form-item label="&nbsp;&nbsp;菜单权限:">
<el-select v-model="fromUpDate.authorityId" placeholder="选择菜单权限" style="width: 240px"> <el-select v-model="fromUpDate.authorityId" placeholder="选择菜单权限" multiple style="width: 240px">
<el-option v-for="item in allPermissionData" :key="item.index" :label="item.authorityName" :value="item.id" /> <el-option v-for="item in allPermissionData" :key="item.id" :label="item.authorityName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -106,32 +106,6 @@
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
<!-- 编辑页面的动作参数弹框 -->
<!-- <el-dialog v-model="visibleParam" title="选择页面" width="500" :before-close="handleCloseParam">
<el-table :data="ParamTableData" style="width: 100%">
<el-table-column label="页面名称" width="180" />
<el-table-column label="页面路径" width="180" />
</el-table>
<
<el-form
ref="formActionRef"
:inline="true"
:model="fromUpDate"
:rules="rules"
style="padding: 24px 40px; font-size: 14px; line-height: 1.5; word-wrap: break-word; font-size: 20px"
>
<el-form-item label="页面路径:" prop="funParam">
<el-input v-model="fromUpDate.funParam" placeholder="" clearable />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="visibleParam = false">取消</el-button>
<el-button type="primary" @click="visibleParam1"> 确定 </el-button>
</div>
</template>
</el-dialog> -->
<!-- 新增弹框 --> <!-- 新增弹框 -->
<el-dialog v-model="visibleAdd" title="新增菜单" width="500" :before-close="handleCloseAdd"> <el-dialog v-model="visibleAdd" title="新增菜单" width="500" :before-close="handleCloseAdd">
<el-form <el-form
@ -170,8 +144,8 @@
</el-form-item> </el-form-item>
<el-form-item label="&nbsp;&nbsp;菜单权限:"> <el-form-item label="&nbsp;&nbsp;菜单权限:">
<el-select v-model="formInlineAdd.authorityId" placeholder="选择菜单权限" style="width: 240px"> <el-select v-model="formInlineAdd.authorityId" placeholder="选择菜单权限" multiple style="width: 240px">
<el-option v-for="item in allPermissionData" :key="item.index" :label="item.authorityName" :value="item.id" /> <el-option v-for="item in allPermissionData" :key="item.id" :label="item.authorityName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -182,37 +156,13 @@
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
<!-- 新增页面动作参数弹框 -->
<!-- <el-dialog v-model="visibleParam" title="选择页面" width="500" :before-close="handleCloseParam">
<el-table :data="ParamTableData" style="width: 100%">
<el-table-column label="页面名称" width="180" />
<el-table-column label="页面路径" width="180" />
</el-table>
<el-form
ref="formActionRef"
:inline="true"
:model="formInlineAdd"
:rules="rules"
style="padding: 24px 40px; font-size: 14px; line-height: 1.5; word-wrap: break-word; font-size: 20px"
>
<el-form-item label="页面路径:" prop="funParam">
<el-input v-model="formInlineAdd.funParam" placeholder="" clearable />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="visibleParam = false">取消</el-button>
<el-button type="primary" @click="visibleParam1"> 确定 </el-button>
</div>
</template>
</el-dialog> -->
<!-- 删除确认弹框 --> <!-- 删除确认弹框 -->
<el-dialog v-model="dialogVisibleDelete" title="操作提示" width="500" :before-close="handleCloseDelete"> <el-dialog v-model="dialogVisibleDelete" title="操作提示" width="500" :before-close="handleCloseDelete">
<span>确定是否删除?</span> <span>确定是否删除?</span>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="dialogVisibleDelete = false">取消</el-button> <el-button @click="dialogVisibleDelete = false">取消</el-button>
<el-button type="primary" @click="dialogVisibleDelete = false"> 确定 </el-button> <el-button type="primary" @click="dialogVisibleDelete1"> 确定 </el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@ -284,15 +234,6 @@ const loadNode = (node: Node, resolve: (data: Tree[]) => void) => {
console.log(err) console.log(err)
}) })
} }
//
const input2 = ref('')
const queryListData = {
menuName: '',
}
const clickQuery = () => {
queryListData.menuName = input2.value
queryMenuMethod(queryListData)
}
// //
const input1 = ref('') const input1 = ref('')
const switchValue = ref(true) const switchValue = ref(true)
@ -320,6 +261,21 @@ const handleNodeClick = (data: Tree) => {
queryMenuMethod(queryData) queryMenuMethod(queryData)
} }
//
const input2 = ref('')
const queryListData = {
menuName: '',
parentMenuId: '',
}
const clickQuery = () => {
queryListData.menuName = input2.value
queryListData.parentMenuId = fromDataId.value
console.log(queryListData, 'queryListDataqueryListData')
queryMenuMethod(queryListData)
}
// //
const queryMenuMethod = (data: any) => { const queryMenuMethod = (data: any) => {
menusQuery(data).then((res) => { menusQuery(data).then((res) => {
@ -365,10 +321,6 @@ const handleCloseAdd = () => {
visibleAdd.value = false visibleAdd.value = false
} }
const handleCloseParam = (done: () => void) => {
visibleParam.value = false
}
interface RuleForm { interface RuleForm {
menuName: string | undefined menuName: string | undefined
menuOrder: number menuOrder: number
@ -496,8 +448,18 @@ interface fromDelete {
const fromDelete = (data: any) => { const fromDelete = (data: any) => {
dialogVisibleDelete.value = true dialogVisibleDelete.value = true
fromDeleteData.id = data.row.id fromDeleteData.id = data.row.id
}
//
const dialogVisibleDelete = ref(false)
const handleCloseDelete = (done: () => void) => {
dialogVisibleDelete.value = false
}
const dialogVisibleDelete1 = (done: () => void) => {
dialogVisibleDelete.value = false
menuDelete(fromDeleteData).then((res) => { menuDelete(fromDeleteData).then((res) => {
console.log(res, data, '删除') console.log(res, '删除')
if (res.code == 200) { if (res.code == 200) {
setTimeout(() => { setTimeout(() => {
ElMessage({ ElMessage({
@ -520,18 +482,6 @@ const fromDelete = (data: any) => {
}) })
} }
//
const dialogVisibleDelete = ref(false)
const handleCloseDelete = (done: () => void) => {
ElMessageBox.confirm('确定是否删除?')
.then(() => {
done()
})
.catch(() => {
// catch error
})
}
// //
const visibleAdd = ref(false) const visibleAdd = ref(false)
@ -569,10 +519,11 @@ const fromAdd = () => {
formInlineAdd.updatedTime = 12345 formInlineAdd.updatedTime = 12345
} }
const addOnSubmit = () => { const addOnSubmit = () => {
formInlineAdd.parentMenuId = fromDataId.value
console.log(formInlineAdd, 'formInlineAdd') console.log(formInlineAdd, 'formInlineAdd')
formRef.value.validate((valid: any) => { formRef.value.validate((valid: any) => {
if (valid) { if (valid) {
alert(1)
formInlineAdd.parentMenuId = fromDataId.value
menuAdd(formInlineAdd).then((res: any) => { menuAdd(formInlineAdd).then((res: any) => {
console.log(res, '增加') console.log(res, '增加')
if (res.code == 200) { if (res.code == 200) {
@ -601,31 +552,6 @@ const addOnSubmit = () => {
}) })
} }
//
const visibleParam = ref(false)
const clickParam = () => {
visibleParam.value = true
}
//
const ParamTableData = reactive([
{
name: '页面名称',
},
{
name: '页面路径',
},
])
const visibleParam1 = () => {
formActionRef.value.validate((valid: any) => {
if (valid) {
visibleParam.value = false
} else {
visibleParam.value = true
}
})
}
// //
const currentPage4 = ref(4) const currentPage4 = ref(4)
const pageSize4 = ref(100) const pageSize4 = ref(100)

View File

@ -4,7 +4,15 @@
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="6" style="padding: 2.2% 1.4%; border-right: 1px solid #eaebed"> <el-col :span="6" style="padding: 2.2% 1.4%; border-right: 1px solid #eaebed">
<el-input v-model="input1" size="large" placeholder="搜索" :suffix-icon="Search" style="width: 100%" /> <el-input v-model="input1" size="large" placeholder="搜索" :suffix-icon="Search" style="width: 100%" />
<el-tree style="max-width: 600px; margin-top: 2.2%" :data="userData" :props="defaultProps" @node-click="handleNodeClick" /> <el-tree
style="max-width: 600px; margin-top: 2.2%"
:data="userData"
:props="defaultProps"
node-key="id"
:load="loadNode"
lazy
@node-click="handleNodeClick"
/>
</el-col> </el-col>
<el-col :span="18" style="padding: 2.2% 1.4%"> <el-col :span="18" style="padding: 2.2% 1.4%">
<el-container> <el-container>
@ -42,34 +50,37 @@
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-main> </el-main>
<!-- <el-footer> <el-footer>
<div style="display: flex; justify-content: right"> <div style="display: flex; justify-content: right">
<el-pagination <el-pagination
v-model:current-page="currentPage4" v-model:current-page="currentPage4"
v-model:page-size="pageSize4" v-model:page-size="pageSize4"
:page-sizes="[10, 15]" :page-sizes="[10, 15]"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
:total="400" :total="paginationTotal"
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
/> />
</div> </div>
</el-footer> --> </el-footer>
</el-container> </el-container>
</el-col> </el-col>
</el-row> </el-row>
<!-- 用户新增页面 --> <!-- 用户新增页面 -->
<el-dialog v-model="visibleParam" title="新增账户" width="500" :before-close="handleCloseParam"> <el-dialog v-model="visibleParam" title="新增账户" width="500" :before-close="handleCloseParam">
<el-form <el-form
ref="formRef"
:inline="true" :inline="true"
label-width="auto"
:model="formUserAdd" :model="formUserAdd"
:rules="rules"
style="padding: 24px 40px; font-size: 14px; line-height: 1.5; word-wrap: break-word; font-size: 20px" style="padding: 24px 40px; font-size: 14px; line-height: 1.5; word-wrap: break-word; font-size: 20px"
> >
<el-form-item label="账户名称:" prop="account"> <el-form-item label="账户名称:" prop="account">
<el-input v-model="formUserAdd.account" placeholder="" clearable /> <el-input v-model="formUserAdd.account" placeholder="" clearable />
</el-form-item> </el-form-item>
<el-form-item label="密码:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"> <el-form-item label="账户密码:" prop="password">
<el-input v-model="formUserAdd.password" placeholder="" type="password" show-password clearable /> <el-input v-model="formUserAdd.password" placeholder="" type="password" show-password clearable />
</el-form-item> </el-form-item>
<el-form-item label="职员名称:" prop="userName"> <el-form-item label="职员名称:" prop="userName">
@ -78,15 +89,15 @@
<el-form-item label="职员邮箱:" prop="email"> <el-form-item label="职员邮箱:" prop="email">
<el-input v-model="formUserAdd.email" placeholder="" clearable /> <el-input v-model="formUserAdd.email" placeholder="" clearable />
</el-form-item> </el-form-item>
<el-form-item label="职员联系电话:" prop="phone"> <el-form-item label="联系电话:" prop="phone">
<el-input v-model="formUserAdd.phone" placeholder="" clearable /> <el-input v-model="formUserAdd.phone" placeholder="" clearable />
</el-form-item> </el-form-item>
<!-- <el-form-item label="所属机构ID:" prop="orgId"> <!-- <el-form-item label="所属机构ID:" prop="orgId">
<el-input v-model="formUserAdd.orgId" placeholder="" clearable /> <el-input v-model="formUserAdd.orgId" placeholder="" clearable />
</el-form-item> --> </el-form-item> -->
<el-form-item label="角色id集合:" prop="roleList"> <el-form-item label="角色权限:" prop="roleList">
<el-select v-model="formUserAdd.roleList" placeholder="选择菜单权限" multiple style="width: 240px"> <el-select v-model="formUserAdd.roleList" placeholder="选择菜单权限" multiple style="width: 240px">
<el-option v-for="item in allPermissionData" :key="item.index" :label="item.roleName" :value="item.id" /> <el-option v-for="item in allPermissionData" :key="item.id" :label="item.roleName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -100,15 +111,18 @@
<!-- 用户修改页面 --> <!-- 用户修改页面 -->
<el-dialog v-model="visibleParamUpData" title="查看账户" width="500" :before-close="handleCloseParamUp"> <el-dialog v-model="visibleParamUpData" title="查看账户" width="500" :before-close="handleCloseParamUp">
<el-form <el-form
ref="formRef"
:inline="true" :inline="true"
label-width="auto"
:model="formUserUpData" :model="formUserUpData"
:rules="rules"
style="padding: 24px 40px; font-size: 14px; line-height: 1.5; word-wrap: break-word; font-size: 20px" style="padding: 24px 40px; font-size: 14px; line-height: 1.5; word-wrap: break-word; font-size: 20px"
> >
<el-form-item label="账户名称:" prop="account"> <el-form-item label="账户名称:" prop="account">
<el-input v-model="formUserUpData.account" placeholder="" clearable /> <el-input v-model="formUserUpData.account" placeholder="" clearable />
</el-form-item> </el-form-item>
<el-form-item label="密码:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" prop="password"> <el-form-item label="账户密码:" prop="password">
<el-input v-model="formUserUpData.password" placeholder="" type="password" show-password clearable /> <el-input v-model="formUserUpData.password" placeholder="" type="password" show-password clearable />
</el-form-item> </el-form-item>
<el-form-item label="职员名称:" prop="userName"> <el-form-item label="职员名称:" prop="userName">
@ -117,15 +131,15 @@
<el-form-item label="职员邮箱:" prop="email"> <el-form-item label="职员邮箱:" prop="email">
<el-input v-model="formUserUpData.email" placeholder="" clearable /> <el-input v-model="formUserUpData.email" placeholder="" clearable />
</el-form-item> </el-form-item>
<el-form-item label="职员联系电话:" prop="phone"> <el-form-item label="联系电话:" prop="phone">
<el-input v-model="formUserUpData.phone" placeholder="" clearable /> <el-input v-model="formUserUpData.phone" placeholder="" clearable />
</el-form-item> </el-form-item>
<!-- <el-form-item label="所属机构ID:" prop="orgId"> <!-- <el-form-item label="所属机构ID:" prop="orgId">
<el-input v-model="formUserUpData.orgId" placeholder="" clearable /> <el-input v-model="formUserUpData.orgId" placeholder="" clearable />
</el-form-item> --> </el-form-item> -->
<el-form-item label="角色id集合:" prop="roleList"> <el-form-item label="角色权限:" prop="roleList">
<el-select v-model="formUserUpData.roleList" placeholder="选择菜单权限" multiple style="width: 240px"> <el-select v-model="formUserUpData.roleList" placeholder="选择菜单权限" multiple style="width: 240px">
<el-option v-for="item in allPermissionData" :key="item.index" :label="item.roleName" :value="item.id" /> <el-option v-for="item in allPermissionData" :key="item.id" :label="item.roleName" :value="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -153,10 +167,10 @@
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, onMounted } from 'vue'
import { Search, CirclePlusFilled } from '@element-plus/icons-vue' import { Search, CirclePlusFilled } from '@element-plus/icons-vue'
import { userQuery, userUpdate, userDelete, userAdd, userList, allRoleQuery } from '/@/api/backend' import { userQuery, userUpdate, userDelete, userAdd, userList, allRoleQuery } from '/@/api/backend'
import { ElTable, ElMessage } from 'element-plus' import { ElTable, ElMessage, FormRules } from 'element-plus'
import { useAdminInfo } from '/@/stores/adminInfo' import { useAdminInfo } from '/@/stores/adminInfo'
import { fa } from 'element-plus/es/locales.mjs' import type Node from 'element-plus/es/components/tree/src/model/node'
import { values } from 'lodash-es'
const adminInfo = useAdminInfo() const adminInfo = useAdminInfo()
const input1 = ref('') const input1 = ref('')
const input2 = ref('') const input2 = ref('')
@ -203,6 +217,27 @@ const handleNodeClick = (data: Tree) => {
RyUserQuery(formQuery) RyUserQuery(formQuery)
} }
const loadNode = (node: Node, resolve: (data: Tree[]) => void) => {
if (node.level === 0) {
return resolve([])
}
const treeQuery = reactive({
parentOrgId: node.data.id,
recursive: false,
})
userList(treeQuery)
.then((res) => {
console.log(res, '树')
// userData.value = res.data
return resolve(res.data)
})
.catch((err) => {
console.log(err)
})
}
const defaultProps = { const defaultProps = {
children: 'children', children: 'children',
label: 'name', label: 'name',
@ -216,8 +251,9 @@ const tableData = ref()
const RyUserQuery = (data: any) => { const RyUserQuery = (data: any) => {
userQuery(data).then((res) => { userQuery(data).then((res) => {
if (res.code == 200) { if (res.code == 200) {
console.log(res.rows, 'res111') console.log(res, 'res111')
tableData.value = res.rows tableData.value = res.rows
paginationTotal.value = res.total
} else { } else {
ElMessage.error({ ElMessage.error({
message: res.msg, message: res.msg,
@ -248,6 +284,8 @@ const formQuery1 = reactive({
const userFromQuery = () => { const userFromQuery = () => {
formQuery1.userName = input2.value formQuery1.userName = input2.value
formQuery1.orgId = treeId.value formQuery1.orgId = treeId.value
console.log(formQuery1, 'formQuery1formQuery1formQuery1')
RyUserQuery(formQuery1) RyUserQuery(formQuery1)
} }
@ -271,7 +309,22 @@ const formUserAdd = reactive({
orgId: '', orgId: '',
roleList: [], roleList: [],
}) })
const rules = reactive<FormRules<RuleUser>>({
account: [
{
required: true,
message: '用户名不能为空',
trigger: 'blur',
},
],
password: [
{
required: true,
message: '用户密码不能为空',
trigger: 'blur',
},
],
})
const addUserFromData = () => { const addUserFromData = () => {
visibleParam.value = true visibleParam.value = true
formUserAdd.account = '' formUserAdd.account = ''
@ -287,21 +340,25 @@ const handleCloseParam = (data: any) => {
visibleParam.value = false visibleParam.value = false
console.log(data) console.log(data)
} }
const formRef = ref()
const addOnSubmit = () => { const addOnSubmit = () => {
visibleParam.value = false formRef.value.validate((valid: any) => {
formUserAdd.orgId = treeId.value if (valid) {
console.log(formUserAdd, treeId.value, 'formUserAdd') visibleParam.value = false
formUserAdd.orgId = treeId.value
console.log(formUserAdd, treeId.value, 'formUserAdd')
userAdd(formUserAdd).then((res) => { userAdd(formUserAdd).then((res) => {
if (res.code == 200) { if (res.code == 200) {
console.log(res, '新增') console.log(res, '新增')
formQuery.orgId = treeId.value formQuery.orgId = treeId.value
RyUserQuery(formQuery) RyUserQuery(formQuery)
} else { } else {
ElMessage.error({ ElMessage.error({
message: res.msg, message: res.msg,
type: 'error', type: 'error',
})
}
}) })
} }
}) })
@ -310,9 +367,9 @@ const addOnSubmit = () => {
// //
const visibleParamUpData = ref(false) const visibleParamUpData = ref(false)
const formUserUpData = reactive({ id: '', account: '', password: '', userName: '', email: '', phone: '', orgId: '', roleList: '' }) const formUserUpData = reactive({ id: '', account: '', password: '', userName: '', email: '', phone: '', orgId: '', roleList: [] })
const viewUsers = (data: any) => { const viewUsers = (data: any) => {
console.log(data.row.roleList, '页面修改数据') console.log(data, '页面修改数据')
visibleParamUpData.value = true visibleParamUpData.value = true
formUserUpData.id = data.row.id formUserUpData.id = data.row.id
formUserUpData.account = data.row.account formUserUpData.account = data.row.account
@ -321,24 +378,28 @@ const viewUsers = (data: any) => {
formUserUpData.email = data.row.email formUserUpData.email = data.row.email
formUserUpData.phone = data.row.phone formUserUpData.phone = data.row.phone
formUserUpData.orgId = data.row.orgId formUserUpData.orgId = data.row.orgId
// formUserUpData.roleList = data.row.roleList formUserUpData.roleList = data.row.roleList
} }
const upDataOnSubmit = () => { const upDataOnSubmit = () => {
console.log(formUserUpData, formUserUpData.roleList, 'formUserUpData') formRef.value.validate((valid: any) => {
if (valid) {
console.log(formUserUpData, formUserUpData.roleList, 'formUserUpData')
userUpdate(formUserUpData).then((res) => { userUpdate(formUserUpData).then((res) => {
if (res.code == 200) { if (res.code == 200) {
console.log(res, '修改成功') console.log(res, '修改成功')
RyUserQuery(formQuery) RyUserQuery(formQuery)
} else { } else {
ElMessage.error({ ElMessage.error({
message: res.msg, message: res.msg,
type: 'error', type: 'error',
})
}
}) })
visibleParamUpData.value = false
} }
}) })
visibleParamUpData.value = false
} }
const handleCloseParamUp = () => { const handleCloseParamUp = () => {
@ -352,21 +413,6 @@ const userListDelete = reactive({
const userFromDelete = (data: any) => { const userFromDelete = (data: any) => {
userDeleteDialog.value = true userDeleteDialog.value = true
userListDelete.id = data.row.id userListDelete.id = data.row.id
userDelete(userListDelete).then((res) => {
if (res.code == 200) {
setTimeout(() => {
ElMessage({
message: res.msg,
type: 'success',
})
}, 1000)
} else {
ElMessage.error({
message: res.msg,
type: 'error',
})
}
})
} }
const userDeleteDialog = ref(false) const userDeleteDialog = ref(false)
@ -377,9 +423,24 @@ const handleCloseDelete = () => {
const userDeleteDialog1 = () => { const userDeleteDialog1 = () => {
userDeleteDialog.value = false userDeleteDialog.value = false
formQuery.orgId = treeId.value userDelete(userListDelete).then((res) => {
console.log(formQuery, 'formQuery') if (res.code == 200) {
RyUserQuery(formQuery) setTimeout(() => {
ElMessage({
message: res.msg,
type: 'success',
})
}, 1000)
formQuery.orgId = treeId.value
console.log(formQuery, 'formQuery')
RyUserQuery(formQuery)
} else {
ElMessage.error({
message: res.msg,
type: 'error',
})
}
})
} }
// //
@ -397,9 +458,9 @@ const allPermission = () => {
} }
// //
const currentPage4 = ref(4) const currentPage4 = ref(0)
const pageSize4 = ref(100) const pageSize4 = ref(10)
const paginationTotal = ref(0)
const handleSizeChange = (val: number) => { const handleSizeChange = (val: number) => {
console.log(`${val} items per page`) console.log(`${val} items per page`)
} }

View File

@ -19,6 +19,7 @@ interface TableDefaultData<T = any> {
} }
interface ApiResponse<T = any> { interface ApiResponse<T = any> {
total: number
code: number code: number
data: T data: T
msg: string msg: string