diff --git a/.env.development b/.env.development index bfdecce..53437f7 100644 --- a/.env.development +++ b/.env.development @@ -8,4 +8,4 @@ VITE_PUBLIC_PATH = / VITE_ROUTER_HISTORY = "hash" # 开发环境后端地址 -VITE_APP_BASE_URL = 'http://192.168.10.13:8000' \ No newline at end of file +VITE_APP_BASE_URL = 'http://192.168.10.14:8008' \ No newline at end of file diff --git a/src/api/home.ts b/src/api/home.ts index eb4d3e7..6cf0506 100644 --- a/src/api/home.ts +++ b/src/api/home.ts @@ -8,14 +8,20 @@ type Result = { type Data = { success: boolean; msg: any; - results?: Array<any>; + data?: Array<any>; }; export const getHomeList = (params?: object) => { - return http.request<Result>("get", baseUrlApi("tps"), { params }); + return http.request<Result>("get", baseUrlApi(""), { params }); }; export const getEvents = (params?: object) => { - return http.request<Data>("get", baseUrlApi("tps/events"), { params }); + return http.request<Data>("get", baseUrlApi("events"), { params }); +}; +export const getScenes = (params?: object) => { + return http.request<Data>("get", baseUrlApi("scenes"), { params }); +}; +export const getReasons = (params?: object) => { + return http.request<Data>("get", baseUrlApi("violation_reasons"), { params }); }; export const updateHomeList = (params?: object) => { return http.request<Data>("put", baseUrlApi(""), { params }); diff --git a/src/api/system.ts b/src/api/system.ts index 78d6973..5983c1c 100644 --- a/src/api/system.ts +++ b/src/api/system.ts @@ -7,7 +7,7 @@ type deptResult = { /** 部门列表查询 */ export const getDeptList = (params?: object) => { - return http.request<deptResult>("get", baseUrlApi("departments/"), { + return http.request<deptResult>("get", baseUrlApi("organization/trees/"), { params }); }; @@ -19,16 +19,20 @@ type deptStatus = { /** 新增部门 */ export const addDept = (data?: object) => { - return http.request<deptStatus>("post", baseUrlApi("departments/"), { - data - }); + return http.request<deptStatus>( + "post", + baseUrlApi("organization/departments/"), + { + data + } + ); }; /** 更新部门 */ export const updateDept = (data?: object | any) => { return http.request<deptStatus>( "put", - baseUrlApi(`departments/${data.id}/`), + baseUrlApi(`organization/departments/${data.id}/`), { data } @@ -39,7 +43,7 @@ export const updateDept = (data?: object | any) => { export const deleteDept = (data?: object | any) => { return http.request<deptStatus>( "delete", - baseUrlApi(`departments/${data}/`), + baseUrlApi(`organization/departments/${data}/`), { data } @@ -55,7 +59,7 @@ type userList = { /** 用户列表查询 */ export const getUserList = (params?: object) => { - return http.request<userList>("get", baseUrlApi("user/"), { + return http.request<userList>("get", baseUrlApi("organization/users/"), { params }); }; @@ -66,19 +70,29 @@ type userStatus = { }; /** 新增用户 */ export const addUser = (data?: object) => { - return http.request<userStatus>("post", baseUrlApi("user/"), { data }); + return http.request<userStatus>("post", baseUrlApi("organization/users/"), { + data + }); }; /** 更新用户 */ export const updateUser = (data?: object | any) => { - return http.request<userStatus>("put", baseUrlApi(`user/${data.id}/`), { - data - }); + return http.request<userStatus>( + "put", + baseUrlApi(`organization/users/${data.id}/`), + { + data + } + ); }; /** 删除用户 */ export const deleteUser = (data?: object | any) => { - return http.request<userStatus>("delete", baseUrlApi(`user/${data}/`), { - data - }); + return http.request<userStatus>( + "delete", + baseUrlApi(`organization/users/${data}/`), + { + data + } + ); }; diff --git a/src/api/user.ts b/src/api/user.ts index 9d8f964..28b3f0c 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -37,7 +37,9 @@ export type RefreshTokenResult = { // return http.request<UserResult>("post", "/login", { data }); // }; export const getLogin = (data?: object) => { - return http.request<UserResult>("post", baseUrlApi("user/login/"), { data }); + return http.request<UserResult>("post", baseUrlApi("organization/login"), { + data + }); }; // export const getLogin = (data?: object) => { diff --git a/src/views/system/dept/form.vue b/src/views/system/dept/form.vue index bc9b6f6..f7f57c1 100644 --- a/src/views/system/dept/form.vue +++ b/src/views/system/dept/form.vue @@ -51,6 +51,7 @@ defineExpose({ getRef }); emitPath: false, checkStrictly: true }" + :disabled="newFormInline.id ? true : false" clearable filterable placeholder="请选择上级部门" diff --git a/src/views/system/dept/utils/hook.tsx b/src/views/system/dept/utils/hook.tsx index 4526fdf..c69730d 100644 --- a/src/views/system/dept/utils/hook.tsx +++ b/src/views/system/dept/utils/hook.tsx @@ -189,6 +189,10 @@ export function useDept() { addDept(params).then(res => { if (res.success) { chores(); + } else { + message(`${res.msg}`, { + type: "warning" + }); } }); } else { diff --git a/src/views/system/user/form.vue b/src/views/system/user/form.vue index fa2ffff..9dd5947 100644 --- a/src/views/system/user/form.vue +++ b/src/views/system/user/form.vue @@ -10,9 +10,10 @@ const props = withDefaults(defineProps<FormProps>(), { department_id: "", username: "", phone_number: "", - status: 1, + is_active: true, gender: null, id: "" + // password: "" }) }); @@ -46,7 +47,7 @@ defineExpose({ getRef }); emitPath: false, checkStrictly: true, disabled: function (data) { - if (data.children && data.children.length > 0) { + if (!data.parent_id) { return true; } else { return false; @@ -75,7 +76,16 @@ defineExpose({ getRef }); /> </el-form-item> </re-col> - + <!-- <re-col> + <el-form-item label="密码" prop="password"> + <el-input + clearable + show-password + v-model="newFormInline.password" + placeholder="密码" + /> + </el-form-item> + </re-col> --> <re-col :value="12" :xs="24" :sm="24"> <el-form-item label="手机号" prop="phone_number"> <el-input @@ -85,18 +95,7 @@ defineExpose({ getRef }); /> </el-form-item> </re-col> - <re-col :value="12" :xs="24" :sm="24"> - <el-form-item label="用户状态"> - <el-switch - v-model="newFormInline.status" - inline-prompt - :active-value="1" - :inactive-value="0" - active-text="已开用" - inactive-text="已关闭" - /> - </el-form-item> - </re-col> + <re-col :value="12" :xs="24" :sm="24"> <el-form-item label="性别" prop="gender"> <el-select v-model="newFormInline.gender" placeholder="请选择"> @@ -106,6 +105,18 @@ defineExpose({ getRef }); </el-select> </el-form-item> </re-col> + <re-col :value="12" :xs="24" :sm="24"> + <el-form-item label="用户状态"> + <el-switch + v-model="newFormInline.is_active" + inline-prompt + :active-value="true" + :inactive-value="false" + active-text="已开用" + inactive-text="已关闭" + /> + </el-form-item> + </re-col> </el-row> </el-form> </template> diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index fc5b769..4a345ab 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -76,15 +76,15 @@ const { class="!w-[160px]" /> </el-form-item> - <el-form-item label="状态:" prop="status"> + <el-form-item label="状态:" prop="is_active"> <el-select - v-model="form.status" + v-model="form.is_active" placeholder="请选择" clearable class="!w-[160px]" > - <el-option label="已开启" value="1" /> - <el-option label="已关闭" value="0" /> + <el-option label="已开启" :value="true" /> + <el-option label="已关闭" :value="false" /> </el-select> </el-form-item> <el-form-item> diff --git a/src/views/system/user/utils/hook.tsx b/src/views/system/user/utils/hook.tsx index f4931da..ea8b81b 100644 --- a/src/views/system/user/utils/hook.tsx +++ b/src/views/system/user/utils/hook.tsx @@ -35,7 +35,7 @@ export function useUser() { /** 手机号 */ phone_number: "", /** 状态 */ - status: "", + is_active: null, /** 部门 */ department_id: "" }); @@ -93,15 +93,15 @@ export function useUser() { }, { label: "状态", - prop: "status", + prop: "is_active", minWidth: 90, cellRenderer: scope => ( <el-switch size={scope.props.size === "small" ? "small" : "default"} loading={switchLoadMap.value[scope.index]?.loading} - v-model={scope.row.status} - active-value={1} - inactive-value={0} + v-model={scope.row.is_active} + active-value={true} + inactive-value={false} active-text="已开启" inactive-text="已关闭" inline-prompt @@ -246,8 +246,8 @@ export function useUser() { department_id: row?.department_id ?? "", username: row?.username ?? "", phone_number: row?.phone_number ?? "", - status: row?.status ?? 1, gender: row?.gender ?? null, + is_active: row?.is_active ?? true, id: row?.id ?? "" } }, @@ -272,7 +272,11 @@ export function useUser() { // 表单规则校验通过 if (title === "新增") { // 实际开发先调用新增接口,再进行下面操作 - addUser(curData).then(res => { + const params = { + ...curData, + password: "test1234" + }; + addUser(params).then(res => { console.log(res); if (res.success) { chores(); @@ -287,7 +291,7 @@ export function useUser() { department_id: curData.department_id, username: curData.username, phone_number: curData.phone_number, - status: curData.status, + is_active: curData.is_active, gender: curData.gender, id: curData.id }; @@ -376,13 +380,24 @@ export function useUser() { isIndeterminate.value = value.length !== allRole.value.length; } + /** 密码正则(密码格式应为8-18位数字、字母、符号的任意两种组合) */ + const REGEXP_PWD = + /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\u4E00-\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){8,18}$/; + function resetPassword(row: { username: string; id: any }) { ElMessageBox.prompt( "请输入用户「" + row.username + "」的新密码", "重置密码", { confirmButtonText: "确定", - cancelButtonText: "取消" + cancelButtonText: "取消", + inputValidator: val => { + if (val === null) { + return true; //初始化的值为null,不做处理的话,刚打开MessageBox就会校验出错,影响用户体验 + } + return REGEXP_PWD.test(val); + }, + inputErrorMessage: "密码格式应为8-18位数字、字母、符号的任意两种组合" } ) .then(({ value }) => { @@ -391,6 +406,30 @@ export function useUser() { type: "warning" }); return false; + } else { + console.log(value); + const params = { + id: row.id, + password: value + }; + updateUser(params) + .then(res => { + console.log(res); + if (res.success) { + message(`${res.msg}`, { + type: "success" + }); + } else { + message(`${res.msg}`, { + type: "warning" + }); + } + }) + .catch(error => { + message(`${error}`, { + type: "warning" + }); + }); } }) .catch(() => {}); diff --git a/src/views/system/user/utils/rule.ts b/src/views/system/user/utils/rule.ts index e1eafe8..ed04b8a 100644 --- a/src/views/system/user/utils/rule.ts +++ b/src/views/system/user/utils/rule.ts @@ -2,6 +2,10 @@ import { reactive } from "vue"; import type { FormRules } from "element-plus"; import { isPhone } from "@pureadmin/utils"; +/** 密码正则(密码格式应为8-18位数字、字母、符号的任意两种组合) */ +export const REGEXP_PWD = + /^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[()])+$)(?!^.*[\u4E00-\u9FA5].*$)([^(0-9a-zA-Z)]|[()]|[a-z]|[A-Z]|[0-9]){8,18}$/; + /** 自定义表单规则校验 */ export const formRules = reactive(<FormRules>{ username: [{ required: true, message: "角色名称为必填项", trigger: "blur" }], @@ -9,9 +13,7 @@ export const formRules = reactive(<FormRules>{ phone_number: [ { validator: (rule, value, callback) => { - if (value === "") { - callback(); - } else if (!isPhone(value)) { + if (!isPhone(value)) { callback(new Error("请输入正确的手机号码格式")); } else { callback(); @@ -21,5 +23,21 @@ export const formRules = reactive(<FormRules>{ // trigger: "click" // 如果想在点击确定按钮时触发这个校验,trigger 设置成 click 即可 } ], - gender: [{ required: true, message: "性别为必填项", trigger: "blur" }] + gender: [{ required: true, message: "性别为必填项", trigger: "blur" }], + password: [ + { + validator: (rule, value, callback) => { + if (value === "") { + callback(new Error("请输入密码")); + } else if (!REGEXP_PWD.test(value)) { + callback( + new Error("密码格式应为8-18位数字、字母、符号的任意两种组合") + ); + } else { + callback(); + } + }, + trigger: "blur" + } + ] }); diff --git a/src/views/system/user/utils/types.ts b/src/views/system/user/utils/types.ts index d4fdc6d..9e79a7f 100644 --- a/src/views/system/user/utils/types.ts +++ b/src/views/system/user/utils/types.ts @@ -2,10 +2,11 @@ interface FormItemProps { higherDeptOptions: Record<string, unknown>[]; username: string; phone_number: string | number; - status: number; + is_active: boolean; department_id: string | number; gender: string | number; id: string | number; + // password: string | number; } interface FormProps { formInline: FormItemProps; diff --git a/src/views/welcome/hook.tsx b/src/views/welcome/hook.tsx index df8554c..60d03e9 100644 --- a/src/views/welcome/hook.tsx +++ b/src/views/welcome/hook.tsx @@ -5,7 +5,7 @@ import { ref, h } from "vue"; export function welcomeUtil() { const currentPlayingIndex = ref(-1); function openDialog(title = "视频", row, index: number) { - console.log(row.video_dir, "row.video_dir"); + console.log(row.video_path, "row.video_path"); addDialog({ title: `${title}用户`, width: "40%", @@ -20,7 +20,7 @@ export function welcomeUtil() { id: "video-" + index, onPlay: () => playVideo(row, index) }, - [h("source", { src: row.video_dir, type: "video/mp4" })] + [h("source", { src: row.video_path, type: "video/mp4" })] ); } }); diff --git a/src/views/welcome/index.vue b/src/views/welcome/index.vue index 507bb54..281e260 100644 --- a/src/views/welcome/index.vue +++ b/src/views/welcome/index.vue @@ -9,7 +9,7 @@ import { type PaginationProps } from "@pureadmin/table"; import { ElMessageBox } from "element-plus"; // import { getConfig } from "@/config"; // import { getToken, formatToken } from "@/utils/auth"; -import { getHomeList, getEvents } from "@/api/home"; +import { getHomeList, getEvents, getScenes, getReasons } from "@/api/home"; import { welcomeUtil } from "./hook"; defineOptions({ @@ -20,10 +20,10 @@ defineOptions({ const { openDialog } = welcomeUtil(); const formInline = reactive({ date: "", - policeId: "", event: "", violation: "", - violationType: "" + violationReason: "", + scene: "" }); const currentPage = ref(1); @@ -37,6 +37,10 @@ const tableData = ref([]); const eventMap = ref({}); +const sceneMap = ref({}); + +const vioReasonMap = ref({}); + const violationMap = ref({ 是: "1", 否: "0", @@ -70,10 +74,10 @@ function onSearch() { const params = { start_time: formInline.date === null ? undefined : formInline.date[0], end_time: formInline.date === null ? undefined : formInline.date[1], - police_id: formInline.policeId || undefined, + scene: formInline.scene || undefined, event_type: formInline.event || undefined, violation: violationMap.value[formInline.violation] || undefined, - violation_type: formInline.violationType || undefined, + violation_type: formInline.violationReason || undefined, page: currentPage.value || undefined, page_size: pageSize.value || undefined }; @@ -165,25 +169,18 @@ const handleClose = (done: () => void) => { }; async function getEvent() { - // axios({ - // url: AdminHostUrl + "events", - // headers: { - // token: formatToken(getToken().accessToken) - // } - // }) - // .then(response => { - // eventMap.value = response.data.data; - // // console.log(eventMap.value); - // }) - // .catch(error => { - // ElMessage({ - // message: "网络暂不通畅", - // type: "warning" - // }); - // console.log(error); - // }); - const { results } = await getEvents(); - eventMap.value = results; + const { data } = await getEvents(); + eventMap.value = data; +} + +async function getScene() { + const { data } = await getScenes(); + sceneMap.value = data; +} + +async function getReason() { + const { data } = await getReasons(); + vioReasonMap.value = data; } function pickerOptions(time) { @@ -202,12 +199,12 @@ const columns: TableColumnList = [ sortable: true }, { - label: "警号", - prop: "police_id", + label: "场景", + prop: "scene", minWidth: 100 }, { - label: "违法行为", + label: "事件类型", prop: "event_type", minWidth: 100 }, @@ -218,24 +215,19 @@ const columns: TableColumnList = [ slot: "violation" }, { - label: "违规行为", - prop: "ai_analysis", - minWidth: 100 - }, - { - label: "时间点", - prop: "relative_time", + label: "违规原因", + prop: "violation_reason", minWidth: 100 }, { label: "缩率图", slot: "image" }, - { - label: "车牌号", - prop: "car_number", - minWidth: 100 - }, + // { + // label: "车牌号", + // prop: "car_number", + // minWidth: 100 + // }, // { // label: "视频", // slot: "video" @@ -294,7 +286,7 @@ onMounted(() => { :default-value="lastMonth" /> </el-form-item> - + <!-- <el-form-item label="警号:"> <el-input v-model="formInline.policeId" @@ -302,15 +294,28 @@ onMounted(() => { clearable style="width: 198px" /> + </el-form-item> --> + <el-form-item label="场景:"> + <el-select + v-model="formInline.scene" + placeholder="场景" + clearable + @click="getScene()" + > + <el-option + v-for="(scene, type) in sceneMap" + :key="type" + :label="scene" + :value="scene" + /> + </el-select> </el-form-item> - - <el-form-item label="违法行为:"> - <!-- <el-input v-model="formInline.event" placeholder="事件"/>--> + <el-form-item label="事件类型:"> <el-select v-model="formInline.event" - placeholder="违法行为" + placeholder="事件类型" clearable - @click="getEvent" + @click="getEvent()" > <el-option v-for="(event, type) in eventMap" @@ -336,13 +341,20 @@ onMounted(() => { </el-select> </el-form-item> - <el-form-item label="违规行为:"> - <el-input - v-model="formInline.violationType" - placeholder="违规行为" + <el-form-item label="违规原因:"> + <el-select + v-model="formInline.violationReason" + placeholder="违规原因" clearable - style="width: 198px" - /> + @click="getReason()" + > + <el-option + v-for="(reason, type) in vioReasonMap" + :key="type" + :label="reason" + :value="reason" + /> + </el-select> </el-form-item> <el-form-item> @@ -380,8 +392,8 @@ onMounted(() => { <el-image preview-teleported loading="lazy" - :src="row.small_image" - :preview-src-list="[row.small_image]" + :src="row.thumbnail" + :preview-src-list="[row.thumbnail]" :initial-index="index" fit="cover" class="w-[100px] h-[100px]" diff --git a/vite.config.ts b/vite.config.ts index 080d488..051bb63 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -45,7 +45,7 @@ export default ({ command, mode }: ConfigEnv): UserConfigExport => { // 本地跨域代理 https://cn.vitejs.dev/config/server-options.html#server-proxy proxy: { "/api": { - target: "http://192.168.10.13:8000", + target: "http://192.168.10.14:8008", changeOrigin: true, rewrite: path => path.replace(/^\/api/, "") }