《一周学完光线追踪》学习 九 电介质材料

camer.h

#pragma once
#ifndef __CAMERA_H__
#define __CAMERA_H__

#include "ray.h"

class camera {
public:
	camera() {
		lower_left_corner = vec3(-2.0, -1.0, -1.0);
		horizontal = vec3(4.0, 0.0, 0.0);
		vertical = vec3(0.0, 2.0, 0.0);
		origin = vec3(0.0, 0.0, 0.0);
	}
	ray get_ray(float u, float v) {
		return ray(origin, lower_left_corner + u * horizontal + v * vertical - origin);
	}
	vec3 lower_left_corner;
	vec3 horizontal;
	vec3 vertical;
	vec3 origin;
};


#endif

dielectric.h

#pragma once
#include "hitable.h"

class dielectric :public material {
public:

	dielectric(float ri) :ref_idx(ri) {}
	virtual bool scatter(const ray&r_in, const hit_record&rec, vec3& attenuation, ray& scattered);
	float ref_idx;
};

hitable.h

#pragma once
#ifndef __HITABLE__H__
#define __HITABLE__H__

#include "ray.h"




class material;

struct hit_record {
	float t;
	vec3 p;
	vec3 normal;
	material* mat_ptr;
};

class hitable {
public:
	virtual bool hit(const ray& r, float t_min, float t_max, hit_record&rec)const = 0;
};


class material {
public:
	virtual bool scatter(const ray &r_in, const hit_record& rec, vec3& attenuation, ray& scattered) = 0;

	vec3 random_in_unit_sphere() {
		vec3 p;

		do {
			p = 2.0 * vec3(rand() / (RAND_MAX + 1.0), rand() / (RAND_MAX + 1.0),
				rand() / (RAND_MAX + 1.0)) - vec3(1, 1, 1); // 生成[-1, 1]的随机数
		} while (dot(p, p) >= 1.0); // 

		return p;
	}
};

class lambertian :public material {
public:


	lambertian(const vec3&a) :albedo(a) {}
	virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered) {
		vec3 target = rec.p + rec.normal + random_in_unit_sphere();
		scattered = ray(rec.p, target - rec.p);
		attenuation = albedo;
		return true;
	}

	vec3 albedo;
};



class metal :public material {
public:
	vec3 reflect(const vec3 &v, const vec3 &n) {
		return v - 2 * dot(v, n)*n;
	}
	metal(const vec3& a, float f) : albedo(a) {
		if (f < 1) fuzz = f;
		else fuzz = 1;
	}
	metal(const vec3&a) :albedo(a) {}
	virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered) {
		vec3 reflected = reflect(unitVector(r_in.direction()), rec.normal);
		scattered = ray(rec.p, reflected + fuzz * random_in_unit_sphere());
		attenuation = albedo;
		return (dot(scattered.direction(), rec.normal) > 0);
	}
	vec3 albedo;
	float fuzz;
};



#endif

hitablelist.h

#pragma once
#ifndef __HITABLELIST_H__
#define __HITABLELIST_H__

#include "hitable.h"

class hitable_list :public hitable {
public:
	hitable_list() {};
	hitable_list(hitable **l, int n) { list = l; list_size = n; }
	virtual bool hit(const ray&r, float tmin, float tmax, hit_record& rec)const;
	hitable **list;
	int list_size;
};


#endif

Ray.h

#ifndef RAY_H
#define RAY_H

#include "Vec3.h"

class ray {
public:

	ray() {}
	ray(const vec3& a, const vec3& b)
	{
		data[0] = a; data[1] = b;
		data[2] = vec3(1.0f / b.x(), 1.0f / b.y(), 1.0f / b.z());

		posneg[0] = (data[1].x() > 0 ? 0 : 1);
		posneg[1] = posneg[0] ^ 1;

		posneg[2] = (data[1].y() > 0 ? 0 : 1);
		posneg[3] = posneg[2] ^ 1;

		posneg[4] = (data[1].z() > 0 ? 0 : 1);
		posneg[5] = posneg[4] ^ 1;
	}

	ray(const ray& r) { *this = r; }
	vec3 origin() const { return data[0]; }
	vec3 direction() const { return data[1]; }
	vec3 invDirection() const { return data[2]; }
	void setOrigin(const vec3& v) { data[0] = v; }
	void setDirection(const vec3& v)
	{
		data[1] = v;
		data[2] = vec3(1.0f / v.x(), 1.0f / v.y(), 1.0f / v.z());

		posneg[0] = (data[1].x() > 0 ? 0 : 1);
		posneg[1] = posneg[0] ^ 1;

		posneg[2] = (data[1].y() > 0 ? 0 : 1);
		posneg[3] = posneg[2] ^ 1;

		posneg[4] = (data[1].z() > 0 ? 0 : 1);
		posneg[5] = posneg[4] ^ 1;
	}
	vec3 pointAtParameter(float t) const { return data[0] + t * data[1]; }

	vec3 data[3];
	int posneg[6];
};


#endif

sphere.h

#pragma once
#ifndef __SPHEREH__
#define __SPHEREH__

#include "hitable.h"
class sphere :public hitable {
public:
	sphere() {}
	sphere(vec3 cen, float r, material* thisMaterial) :center(cen), radius(r), m_material(thisMaterial) {};
	sphere(vec3 cen, float r) :center(cen), radius(r) {};
	virtual bool hit(const ray&r, float t_min, float t_max, hit_record&rec)const;
	vec3 center;
	float radius;
	material* m_material;
};


#endif

vec3.h

#ifndef VECTOR3_H
#define VECTOR3_H



#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream>
#include <iomanip>




class vec3 {
public:

	vec3() { e[0] = 0; e[1] = 0; e[2] = 0; }
	vec3(float e0, float e1, float e2) { e[0] = e0; e[1] = e1; e[2] = e2; }
	float x() const { return e[0]; }
	float y() const { return e[1]; }
	float z() const { return e[2]; }
	void setX(float a) { e[0] = a; }
	void setY(float a) { e[1] = a; }
	void setZ(float a) { e[2] = a; }

	inline vec3(const vec3 &v) {
		e[0] = v.e[0]; e[1] = v.e[1]; e[2] = v.e[2];
	}

	const vec3& operator+() const { return *this; }
	vec3 operator-() const { return vec3(-e[0], -e[1], -e[2]); }
	float& operator[](int i) { return e[i]; }
	float operator[](int i) const { return e[i]; }

	vec3& operator+=(const vec3& v2);
	vec3& operator-=(const vec3& v2);
	vec3& operator*=(const vec3& v2);
	vec3& operator*=(const float t);
	vec3& operator/=(const float t);



	float length() const { return sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]); }
	float squaredLength() const { return e[0] * e[0] + e[1] * e[1] + e[2] * e[2]; }

	void makeUnitVector();


	float minComponent() const { return e[indexOfMinComponent()]; }
	float maxComponent() const { return e[indexOfMaxComponent()]; }
	float maxAbsComponent() const { return e[indexOfMaxAbsComponent()]; }
	float minAbsComponent() const { return e[indexOfMinAbsComponent()]; }
	int indexOfMinComponent() const {
		return (e[0] < e[1] && e[0] < e[2]) ? 0 : (e[1] < e[2] ? 1 : 2);
	}

	int indexOfMinAbsComponent() const {
		if (fabs(e[0]) < fabs(e[1]) && fabs(e[0]) < fabs(e[2]))
			return 0;
		else if (fabs(e[1]) < fabs(e[2]))
			return 1;
		else
			return 2;
	}

	int indexOfMaxComponent() const {
		return (e[0] > e[1] && e[0] > e[2]) ? 0 : (e[1] > e[2] ? 1 : 2);
	}

	int indexOfMaxAbsComponent() const {
		if (fabs(e[0]) > fabs(e[1]) && fabs(e[0]) > fabs(e[2]))
			return 0;
		else if (fabs(e[1]) > fabs(e[2]))
			return 1;
		else
			return 2;
	}

	float e[3];
};


inline bool operator==(const vec3 &t1, const vec3 &t2) {
	return ((t1[0] == t2[0]) && (t1[1] == t2[1]) && (t1[2] == t2[2]));
}

inline bool operator!=(const vec3 &t1, const vec3 &t2) {
	return ((t1[0] != t2[0]) || (t1[1] != t2[1]) || (t1[2] != t2[2]));
}

inline vec3 unitVector(const vec3& v) {
	float k = 1.0f / sqrt(v.e[0] * v.e[0] + v.e[1] * v.e[1] + v.e[2] * v.e[2]);
	return vec3(v.e[0] * k, v.e[1] * k, v.e[2] * k);
}

inline void vec3::makeUnitVector() {
	float k = 1.0f / sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
	e[0] *= k; e[1] *= k; e[2] *= k;
}

inline vec3 operator+(const vec3 &v1, const vec3 &v2) {
	return vec3(v1.e[0] + v2.e[0], v1.e[1] + v2.e[1], v1.e[2] + v2.e[2]);
}

inline vec3 operator-(const vec3 &v1, const vec3 &v2) {
	return vec3(v1.e[0] - v2.e[0], v1.e[1] - v2.e[1], v1.e[2] - v2.e[2]);
}

inline vec3 operator*(float t, const vec3 &v) {
	return vec3(t*v.e[0], t*v.e[1], t*v.e[2]);
}

inline vec3 operator*(const vec3 &v, float t) {
	return vec3(t*v.e[0], t*v.e[1], t*v.e[2]);
}

inline vec3 operator/(const vec3 &v, float t) {
	return vec3(v.e[0] / t, v.e[1] / t, v.e[2] / t);
}

inline vec3 operator*(const vec3& v, const vec3& v2) {
	return vec3(v.e[0] * v2.e[0], v.e[1] * v2.e[1], v.e[2] * v2.e[2]);
}

inline float dot(const vec3 &v1, const vec3 &v2) {
	return v1.e[0] * v2.e[0] + v1.e[1] * v2.e[1] + v1.e[2] * v2.e[2];
}

inline vec3 cross(const vec3 &v1, const vec3 &v2) {
	return vec3((v1.e[1] * v2.e[2] - v1.e[2] * v2.e[1]),
		(v1.e[2] * v2.e[0] - v1.e[0] * v2.e[2]),
		(v1.e[0] * v2.e[1] - v1.e[1] * v2.e[0]));
}


inline vec3& vec3::operator+=(const vec3 &v) {
	e[0] += v.e[0];
	e[1] += v.e[1];
	e[2] += v.e[2];
	return *this;
}

inline vec3& vec3::operator-=(const vec3& v) {
	e[0] -= v.e[0];
	e[1] -= v.e[1];
	e[2] -= v.e[2];
	return *this;
}

inline vec3& vec3::operator*=(const float t) {
	e[0] *= t;
	e[1] *= t;
	e[2] *= t;
	return *this;
}

inline vec3& vec3::operator/=(const float t) {
	e[0] /= t;
	e[1] /= t;
	e[2] /= t;
	return *this;
}

inline
vec3 reflect(const vec3& in, const vec3& normal)
{
	// assumes unit length normal
	return in - normal * (2 * dot(in, normal));
}


#endif

dielectric.cpp

#include "dielectric.h"
inline bool refract(const vec3&v, const vec3 &n, float ni_over_nt, vec3& refracted) {
	vec3 uv = unitVector(v);
	float dt = dot(uv, n);
	float discriminant = 1.0 - ni_over_nt * ni_over_nt*(1 - dt * dt);
	if (discriminant > 0) {
		refracted = ni_over_nt * (uv - n * dt) - n * sqrt(discriminant);
		return true;
	}
	else
		return false;
}

bool dielectric::scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered) {
	vec3 outward_normal;
	vec3 reflected = reflect(r_in.direction(), rec.normal);
	float ni_over_nt;
	/* ni_over_nt为入射介质的折射指数和折射介质的折射指数的比值*/
	attenuation = vec3(1.0, 1.0, 1.0);
	/*介质的衰减向量为(1,1,1)不是光线不衰减*/
	vec3 refracted;
	if (dot(r_in.direction(), rec.normal) > 0) {
		/* 光线的方向向量和球的法向量的点乘大于零,说明光线是从球体内部射入空气。所以,入射时的法向量和球的法向量方向相反;注意,ref_idx是指光密介质的折射指数和光疏介质的折射指数的比值,此时入射介质是光密介质,折射介质是光疏介质,所以ni_over_nt=ref_idx*/
		outward_normal = -rec.normal;
		ni_over_nt = ref_idx;
	}
	else {
		/*光线的方向向量和球的法向量的点乘bu大于零,说明光线是从空气射入球体气。所以,入射时的法向量和球的法向量方向同向;注意,ref_idx是指光密介质的折射指数和光疏介质的折射指数的比值,此时入射介质是光疏介质,折射介质是光密介质,所以ni_over_nt=1.0/ref_idx*/
		outward_normal = rec.normal;
		ni_over_nt = 1.0 / ref_idx;
	}
	if (refract(r_in.direction(), outward_normal, ni_over_nt, refracted)) {
		scattered = ray(rec.p, refracted);
	}
	else {
		/*计算折射光线方向向量的函数返回false,即出现全反射。但是,本章节讨论的是均匀球体,是不会有全反射的,所以,次数也返回false*/
		scattered = ray(rec.p, reflected);
		return false;
	}
	/*注意:这里只判断了“有没有折射光线”,除了全反射的情况,其他情况都是有折射光线的;而没有判断“有没有反射光线”,全反射是反射光线的一种,其他情况也都是有反射光线的,但是此处不考虑*/
	return true;
}

hitablelist.cpp

#include "hitablelist.h"
bool hitable_list::hit(const ray&r, float tmin, float tmax, hit_record& rec)const {
	hit_record temp_rec;
	bool hit_anything = false;
	double closest_so_far = tmax;
	for (int i = 0; i < list_size; i++) {
		if (list[i]->hit(r, tmin, closest_so_far, temp_rec)) {
			hit_anything = true;
			closest_so_far = temp_rec.t;
			rec = temp_rec;
		}
	}
	return hit_anything;
}

main.cpp

#include <stdlib.h>
#ifdef _WIN64
#define GLUT_NO_LIB_PRAGMA
#pragma comment (lib, "opengl32.lib")  // link with Microsoft OpenGL lib 
#pragma comment (lib, "glut64.lib")    // link with Win64 GLUT lib 
#endif //_WIN64
#ifdef _WIN32
//On Windows, include the local copy of glut.h and glext.h
#include "glut.h"
#include "glext.h"
#define GET_PROC_ADDRESS( str ) wglGetProcAddress( str )
#endif
#include "vec3.h"
#include "ray.h"
#define WIDTH 400
#define HEIGHT 200
unsigned char *Pixels;
#include "hitable.h"
#include "Sphere.h"
#include "hitablelist.h"
#define MAXFLOAT 20.0
#include "camera.h"
#include "time.h"
#include "dielectric.h"


vec3 color(const ray&r, hitable *world, int depth) {
	hit_record rec;
	if (world->hit(r, 0.001, MAXFLOAT, rec)) {
		ray scattered;
		vec3 attenuation;
		if (depth < 50 && rec.mat_ptr->scatter(r, rec, attenuation, scattered)) {
			return attenuation * color(scattered, world, depth + 1);
		}
		else {
			return vec3(0, 0, 0);
		}
	}
	else {
		vec3 unit_direction = unitVector(r.direction());
		float t = 0.5*(unit_direction.y() + 1.0);
		return (1.0 - t)*vec3(1.0, 1.0, 1.0) + t * vec3(0.5, 0.7, 1.0);
	}
}


void Draw(void) {
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClear(GL_COLOR_BUFFER_BIT);
	glDrawPixels(WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, Pixels);
	glFlush();
}

int main() {
	srand(time(NULL));
	Pixels = (unsigned char*)malloc(WIDTH*HEIGHT * sizeof(unsigned char) * 4);
	hitable *list[4];
	list[0] = new sphere(vec3(0, 0, -1.0), 0.5, new lambertian(vec3(0.8, 0.3, 0.3)));
	list[1] = new sphere(vec3(0.0, -100.5, -1.0), 100, new lambertian(vec3(0.8, 0.8, 0.0)));
	list[2] = new sphere(vec3(1.0, 0.0, -1.0), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.3));
	list[3] = new sphere(vec3(-1.0, 0.0, -1.0), 0.5, new dielectric(1.5));

	hitable *world = new hitable_list(list, 4);
	camera cam;
	int ns = 100;
	for (int j = HEIGHT - 1; j >= 0; j--) {
		for (int i = 0; i < WIDTH; i++) {
			vec3 col(0, 0, 0);
			for (int s = 0; s < ns; s++) {
				float u = float(i + rand() / (RAND_MAX + 1.0)) / float(WIDTH);
				float v = float(j + rand() / (RAND_MAX + 1.0)) / float(HEIGHT);
				ray r = cam.get_ray(u, v);
				vec3 p = r.pointAtParameter(2.0);
				col += color(r, world, 0);
			}
			col /= float(ns);
			col = vec3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2]));
			int offset = (WIDTH * j + i) * 4;
			Pixels[offset + 0] = (unsigned char)255.99*col[0];
			Pixels[offset + 1] = (unsigned char)255.99*col[1];
			Pixels[offset + 2] = (unsigned char)255.99*col[2];
			Pixels[offset + 3] = 255;
		}
	}

	int argc = 0; char *argv = const_cast<char*>("");
	glutInit(&argc, &argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
	glutInitWindowSize(WIDTH, HEIGHT);
	glutCreateWindow("bitmap");
	glutDisplayFunc(Draw);
	glutMainLoop();
}

sphere.cpp

#include "sphere.h"
bool sphere::hit(const ray&r, float t_min, float t_max, hit_record&rec)const {
	vec3 oc = r.origin() - center;
	float a = dot(r.direction(), r.direction());
	float b = 2.0 * dot(oc, r.direction());
	float c = dot(oc, oc) - radius * radius;
	float discriminant = b * b - 4 * a * c;

	if (discriminant > 0) {
		float temp = (-b - sqrt(discriminant)) / (2.0*a);
		if (temp < t_max && temp > t_min) {
			rec.t = temp;
			rec.p = r.pointAtParameter(rec.t);
			rec.normal = (rec.p - center) / radius;
			rec.mat_ptr = m_material;
			return true;
		}

		temp = (-b + sqrt(discriminant)) / (2.0*a);

		if (temp < t_max && temp > t_min) {
			rec.t = temp;
			rec.p = r.pointAtParameter(rec.t);
			rec.normal = (rec.p - center) / radius;
			rec.mat_ptr = m_material;
			return true;
		}
	}

	return false;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
大学生在线租房平台管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、报修评价管理、字典管理、房东管理、房屋管理、房屋收藏管理、房屋留言管理、房屋租赁管理、租房论坛管理、公告信息管理、留言板管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 大学生在线租房平台管理系统可以提高大学生在线租房平台信息管理问题的解决效率,优化大学生在线租房平台信息处理流程,保证大学生在线租房平台信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理大学生在线租房平台信息,包括房屋管理,培训管理,报修管理,薪资管理等,可以管理公告。 房屋管理界面,管理员在房屋管理界面中可以对界面中显示,可以对房屋信息的房屋状态进行查看,可以添加新的房屋信息等。报修管理界面,管理员在报修管理界面中查看报修种类信息,报修描述信息,新增报修信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值